@paymanai/payman-typescript-ask-sdk 1.2.8 → 1.2.10

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.
@@ -500,8 +500,78 @@ function processStreamEvent(event, state) {
500
500
 
501
501
  // src/utils/messageStateManager.ts
502
502
  var FRIENDLY_ERROR_MESSAGE = "Oops, something went wrong. Please try again.";
503
+ function buildFormattedThinking(steps, allThinkingText) {
504
+ const parts = [];
505
+ const safeSteps = steps ?? [];
506
+ const cleanAll = allThinkingText.replace(/^\s+/, "");
507
+ if (cleanAll) {
508
+ const firstStepWithThinking = safeSteps.find(
509
+ (s) => s.thinkingText && s.thinkingText.trim()
510
+ );
511
+ if (!firstStepWithThinking) {
512
+ parts.push("**Preflight**");
513
+ parts.push(cleanAll);
514
+ } else {
515
+ const stepText = firstStepWithThinking.thinkingText.trim();
516
+ const idx = cleanAll.indexOf(stepText);
517
+ if (idx > 0) {
518
+ const orphaned = cleanAll.substring(0, idx).replace(/\s+$/, "");
519
+ if (orphaned) {
520
+ parts.push("**Preflight**");
521
+ parts.push(orphaned);
522
+ }
523
+ }
524
+ }
525
+ }
526
+ for (const step of safeSteps) {
527
+ switch (step.eventType) {
528
+ case "ORCHESTRATOR_THINKING":
529
+ parts.push("**Planning**");
530
+ if (step.message) parts.push(step.message);
531
+ break;
532
+ case "INTENT_STARTED": {
533
+ let label = step.message || "Processing";
534
+ const started = label.match(/^(.+?)\s+started$/i);
535
+ const progress = label.match(/^(.+?)\s+in progress$/i);
536
+ if (started) label = started[1];
537
+ else if (progress) label = progress[1];
538
+ parts.push(`**${label}**`);
539
+ if (step.thinkingText) parts.push(step.thinkingText);
540
+ break;
541
+ }
542
+ case "INTENT_PROGRESS": {
543
+ if (step.thinkingText) parts.push(step.thinkingText);
544
+ else if (step.message) parts.push(step.message);
545
+ break;
546
+ }
547
+ case "AGGREGATOR_THINKING":
548
+ parts.push("**Finalizing**");
549
+ if (step.message) parts.push(step.message);
550
+ break;
551
+ case "USER_ACTION_REQUIRED":
552
+ parts.push("**Verification Required**");
553
+ if (step.message) parts.push(step.message);
554
+ break;
555
+ case "USER_ACTION_SUCCESS":
556
+ parts.push(`\u2713 ${step.message || "Verification successful"}`);
557
+ break;
558
+ case "USER_ACTION_REJECTED":
559
+ parts.push(`\u2717 ${step.message || "Verification rejected"}`);
560
+ break;
561
+ case "USER_ACTION_EXPIRED":
562
+ parts.push(`\u2717 ${step.message || "Verification expired"}`);
563
+ break;
564
+ case "USER_ACTION_FAILED":
565
+ parts.push(`\u2717 ${step.message || "Verification failed"}`);
566
+ break;
567
+ }
568
+ }
569
+ return parts.length > 0 ? parts.join("\n") : allThinkingText;
570
+ }
503
571
  function createStreamingMessageUpdate(state) {
504
572
  const hasCompletedContent = state.accumulatedContent && state.finalData !== void 0;
573
+ const steps = state.hasError ? [] : [...state.steps];
574
+ const allThinking = state.hasError ? void 0 : state.allThinkingText;
505
575
  return {
506
576
  streamingContent: state.hasError ? FRIENDLY_ERROR_MESSAGE : hasCompletedContent ? state.accumulatedContent : "",
507
577
  content: state.hasError ? FRIENDLY_ERROR_MESSAGE : "",
@@ -511,12 +581,13 @@ function createStreamingMessageUpdate(state) {
511
581
  errorDetails: state.hasError ? state.errorMessage : void 0,
512
582
  executionId: state.executionId,
513
583
  sessionId: state.sessionId,
514
- steps: state.hasError ? [] : [...state.steps],
584
+ steps,
515
585
  currentExecutingStepId: state.hasError ? void 0 : state.currentExecutingStepId,
516
586
  isCancelled: false,
517
587
  userActionResult: state.userActionResult,
518
588
  activeThinkingText: state.hasError ? void 0 : state.activeThinkingText,
519
- allThinkingText: state.hasError ? void 0 : state.allThinkingText
589
+ allThinkingText: allThinking,
590
+ formattedThinkingText: state.hasError ? void 0 : buildFormattedThinking(steps, allThinking || "")
520
591
  };
521
592
  }
522
593
  function createErrorMessageUpdate(error, state) {
@@ -540,6 +611,8 @@ function createErrorMessageUpdate(error, state) {
540
611
  };
541
612
  }
542
613
  function createFinalMessage(streamingId, state) {
614
+ const steps = state.hasError ? [] : [...state.steps];
615
+ const allThinking = state.hasError ? void 0 : state.allThinkingText;
543
616
  return {
544
617
  id: streamingId,
545
618
  sessionId: state.sessionId,
@@ -552,12 +625,14 @@ function createFinalMessage(streamingId, state) {
552
625
  errorDetails: state.hasError ? state.errorMessage : void 0,
553
626
  executionId: state.executionId,
554
627
  tracingData: state.finalData,
555
- steps: state.hasError ? [] : [...state.steps],
628
+ steps,
556
629
  isCancelled: false,
557
630
  currentExecutingStepId: void 0,
558
631
  userActionResult: state.userActionResult,
559
632
  activeThinkingText: void 0,
560
- allThinkingText: state.hasError ? void 0 : state.allThinkingText
633
+ allThinkingText: allThinking,
634
+ formattedThinkingText: state.hasError ? void 0 : buildFormattedThinking(steps, allThinking || ""),
635
+ isResolvingImages: state.hasError ? void 0 : state.isResolvingImages
561
636
  };
562
637
  }
563
638
  function createCancelledMessageUpdate(steps, currentMessage) {
@@ -611,6 +686,16 @@ function buildUserActionUrl(config, userActionId, action) {
611
686
  const encodedUserActionId = encodeURIComponent(userActionId);
612
687
  return `${config.api.baseUrl}${basePath}/user-action/${encodedUserActionId}/${action}`;
613
688
  }
689
+ function buildResolveImagesUrl(config) {
690
+ if (config.api.resolveImagesEndpoint) {
691
+ return `${config.api.baseUrl}${config.api.resolveImagesEndpoint}`;
692
+ }
693
+ const streamEndpoint = config.api.streamEndpoint || "/api/workflows/ask/stream";
694
+ const [endpointPath] = streamEndpoint.split("?");
695
+ const normalizedEndpointPath = endpointPath.replace(/\/+$/, "");
696
+ const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
697
+ return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
698
+ }
614
699
  function buildRequestHeaders(config) {
615
700
  const headers = {
616
701
  ...config.api.headers
@@ -729,6 +814,58 @@ var activeStreamStore = {
729
814
  streams.delete(key);
730
815
  }
731
816
  };
817
+
818
+ // src/utils/ragImageResolver.ts
819
+ var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
820
+ function hasRagImages(content) {
821
+ return RAG_IMAGE_REGEX.test(content);
822
+ }
823
+ async function waitForNextPaint(signal) {
824
+ if (signal?.aborted) return;
825
+ await new Promise((resolve) => {
826
+ let isSettled = false;
827
+ const finish = () => {
828
+ if (isSettled) return;
829
+ isSettled = true;
830
+ signal?.removeEventListener("abort", finish);
831
+ resolve();
832
+ };
833
+ signal?.addEventListener("abort", finish, { once: true });
834
+ if (typeof requestAnimationFrame === "function") {
835
+ requestAnimationFrame(() => {
836
+ setTimeout(finish, 0);
837
+ });
838
+ return;
839
+ }
840
+ setTimeout(finish, 0);
841
+ });
842
+ }
843
+ async function resolveRagImageUrls(config, content, signal) {
844
+ const url = buildResolveImagesUrl(config);
845
+ const baseHeaders = buildRequestHeaders(config);
846
+ const headers = { "Content-Type": "application/json", ...baseHeaders };
847
+ const response = await fetch(url, {
848
+ method: "POST",
849
+ headers,
850
+ body: JSON.stringify({ input: content }),
851
+ signal
852
+ });
853
+ if (!response.ok) {
854
+ const errorText = await response.text();
855
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
856
+ }
857
+ const text = await response.text();
858
+ try {
859
+ const parsed = JSON.parse(text);
860
+ if (typeof parsed === "string") return parsed;
861
+ if (typeof parsed.output === "string") return parsed.output;
862
+ if (typeof parsed.result === "string") return parsed.result;
863
+ } catch {
864
+ }
865
+ return text;
866
+ }
867
+
868
+ // src/hooks/useStreamManager.ts
732
869
  function useStreamManager(config, callbacks, setMessages, setIsWaitingForResponse) {
733
870
  const abortControllerRef = react.useRef(null);
734
871
  const configRef = react.useRef(config);
@@ -894,9 +1031,11 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
894
1031
  if (state.currentSessionId && state.currentSessionId !== sessionId) {
895
1032
  callbacksRef.current.onSessionIdChange?.(state.currentSessionId);
896
1033
  }
1034
+ const needsImageResolve = !state.hasError && !abortController.signal.aborted && hasRagImages(state.accumulatedContent);
897
1035
  const finalMessage = createFinalMessage(streamingId, {
898
1036
  ...state,
899
- sessionId: state.currentSessionId || sessionId
1037
+ sessionId: state.currentSessionId || sessionId,
1038
+ isResolvingImages: needsImageResolve
900
1039
  });
901
1040
  setMessages(
902
1041
  (prev) => prev.map(
@@ -907,6 +1046,30 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
907
1046
  }
908
1047
  });
909
1048
  clearThrottle();
1049
+ const shouldResolveImages = !abortController.signal.aborted && !state.hasError && hasRagImages(state.accumulatedContent);
1050
+ if (shouldResolveImages) {
1051
+ await waitForNextPaint(abortController.signal);
1052
+ }
1053
+ if (shouldResolveImages && !abortController.signal.aborted) {
1054
+ try {
1055
+ const resolvedContent = await resolveRagImageUrls(
1056
+ currentConfig,
1057
+ state.accumulatedContent,
1058
+ abortController.signal
1059
+ );
1060
+ setMessages(
1061
+ (prev) => prev.map(
1062
+ (msg) => msg.id === streamingId ? { ...msg, content: resolvedContent, isResolvingImages: false } : msg
1063
+ )
1064
+ );
1065
+ } catch {
1066
+ setMessages(
1067
+ (prev) => prev.map(
1068
+ (msg) => msg.id === streamingId ? { ...msg, isResolvingImages: false } : msg
1069
+ )
1070
+ );
1071
+ }
1072
+ }
910
1073
  return state.currentSessionId;
911
1074
  } catch (error) {
912
1075
  clearThrottle();
@@ -1238,6 +1401,912 @@ function useChat(config, callbacks = {}) {
1238
1401
  resendOtp
1239
1402
  };
1240
1403
  }
1404
+
1405
+ // src/utils/v2EventProcessor.ts
1406
+ function getEventText(event, field) {
1407
+ const value = event[field];
1408
+ return typeof value === "string" ? value.trim() : "";
1409
+ }
1410
+ function shouldShowIntentHeader(event) {
1411
+ const workerName = getEventText(event, "workerName");
1412
+ const intentId = getEventText(event, "intentId");
1413
+ return Boolean(workerName && intentId && workerName === intentId);
1414
+ }
1415
+ function addThinkingHeader(state, header) {
1416
+ state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + header;
1417
+ }
1418
+ function addThinkingDetail(state, detail) {
1419
+ const trimmed = detail.trim();
1420
+ if (!trimmed) return;
1421
+ state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + trimmed;
1422
+ }
1423
+ function addThinkingLine(state, header, detail) {
1424
+ state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + header + "\n" + detail;
1425
+ }
1426
+ function appendThinkingText(state, text) {
1427
+ state.formattedThinkingText += text;
1428
+ }
1429
+ function completeLastInProgressStep2(steps) {
1430
+ for (let i = steps.length - 1; i >= 0; i--) {
1431
+ if (steps[i].status === "in_progress") {
1432
+ steps[i].status = "completed";
1433
+ return;
1434
+ }
1435
+ }
1436
+ }
1437
+ function createInitialV2State() {
1438
+ return {
1439
+ formattedThinkingText: "",
1440
+ finalResponse: "",
1441
+ currentWorker: "",
1442
+ lastEventType: "",
1443
+ sessionId: void 0,
1444
+ executionId: void 0,
1445
+ hasError: false,
1446
+ errorMessage: "",
1447
+ userActionRequest: void 0,
1448
+ userActionPending: false,
1449
+ userActionResult: void 0,
1450
+ finalData: void 0,
1451
+ steps: [],
1452
+ stepCounter: 0,
1453
+ currentExecutingStepId: void 0
1454
+ };
1455
+ }
1456
+ function processStreamEventV2(event, state) {
1457
+ const eventType = event.eventType;
1458
+ if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
1459
+ if (event.executionId) state.executionId = event.executionId;
1460
+ if (event.sessionId) state.sessionId = event.sessionId;
1461
+ return state;
1462
+ }
1463
+ if (event.executionId) state.executionId = event.executionId;
1464
+ if (event.sessionId) state.sessionId = event.sessionId;
1465
+ const message = getEventMessage(event);
1466
+ switch (eventType) {
1467
+ case "WORKFLOW_STARTED":
1468
+ case "STARTED":
1469
+ state.lastEventType = eventType;
1470
+ break;
1471
+ case "INTENT_THINKING": {
1472
+ const worker = getEventText(event, "workerName") || "Worker";
1473
+ const msg = getEventText(event, "message") || "Thinking...";
1474
+ const showHeader = shouldShowIntentHeader(event);
1475
+ if (worker !== state.currentWorker) {
1476
+ state.currentWorker = worker;
1477
+ if (showHeader && msg && msg !== worker) {
1478
+ addThinkingLine(state, `**${worker}**`, msg);
1479
+ } else if (showHeader) {
1480
+ addThinkingHeader(state, `**${worker}**`);
1481
+ } else if (msg !== "Thinking...") {
1482
+ addThinkingDetail(state, msg);
1483
+ }
1484
+ } else if ((showHeader || msg !== "Thinking...")) {
1485
+ appendThinkingText(state, "\n" + msg);
1486
+ }
1487
+ const lastInProgress = [...state.steps].reverse().find((s) => s.status === "in_progress");
1488
+ if (lastInProgress) {
1489
+ lastInProgress.thinkingText = "";
1490
+ lastInProgress.isThinking = true;
1491
+ }
1492
+ state.lastEventType = "INTENT_THINKING";
1493
+ break;
1494
+ }
1495
+ case "INTENT_THINKING_CONT": {
1496
+ const msg = event.message || "";
1497
+ if (!msg) break;
1498
+ if (state.lastEventType === "INTENT_THINKING") {
1499
+ appendThinkingText(state, "\n" + msg);
1500
+ } else {
1501
+ appendThinkingText(state, msg);
1502
+ }
1503
+ const thinkingStep = [...state.steps].reverse().find((s) => s.isThinking);
1504
+ if (thinkingStep) {
1505
+ thinkingStep.thinkingText = (thinkingStep.thinkingText || "") + msg;
1506
+ }
1507
+ state.lastEventType = "INTENT_THINKING_CONT";
1508
+ break;
1509
+ }
1510
+ case "ORCHESTRATOR_THINKING": {
1511
+ addThinkingLine(state, "**Planning**", event.message || "Understanding your request...");
1512
+ const stepId = `step-${state.stepCounter++}`;
1513
+ state.steps.push({
1514
+ id: stepId,
1515
+ eventType,
1516
+ message,
1517
+ status: "in_progress",
1518
+ timestamp: Date.now(),
1519
+ elapsedMs: event.elapsedMs
1520
+ });
1521
+ state.currentExecutingStepId = stepId;
1522
+ state.lastEventType = eventType;
1523
+ break;
1524
+ }
1525
+ case "ORCHESTRATOR_COMPLETED": {
1526
+ appendThinkingText(state, "\n" + (event.message || "Planning complete"));
1527
+ const step = state.steps.find((s) => s.eventType === "ORCHESTRATOR_THINKING" && s.status === "in_progress");
1528
+ if (step) {
1529
+ step.status = "completed";
1530
+ if (event.elapsedMs) step.elapsedMs = event.elapsedMs;
1531
+ if (step.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
1532
+ }
1533
+ state.lastEventType = eventType;
1534
+ break;
1535
+ }
1536
+ case "INTENT_STARTED": {
1537
+ const worker = getEventText(event, "workerName") || "Worker";
1538
+ const msg = getEventText(event, "message") || "Starting...";
1539
+ const showHeader = shouldShowIntentHeader(event);
1540
+ state.currentWorker = worker;
1541
+ if (showHeader && msg !== worker) {
1542
+ addThinkingLine(state, `**${worker}**`, msg);
1543
+ } else if (showHeader) {
1544
+ addThinkingHeader(state, `**${worker}**`);
1545
+ } else {
1546
+ addThinkingDetail(state, msg);
1547
+ }
1548
+ const thinkingStep = state.steps.find((s) => s.isThinking);
1549
+ if (thinkingStep) thinkingStep.isThinking = false;
1550
+ const stepId = `step-${state.stepCounter++}`;
1551
+ state.steps.push({
1552
+ id: stepId,
1553
+ eventType,
1554
+ message,
1555
+ status: "in_progress",
1556
+ timestamp: Date.now(),
1557
+ elapsedMs: event.elapsedMs
1558
+ });
1559
+ state.currentExecutingStepId = stepId;
1560
+ state.lastEventType = eventType;
1561
+ break;
1562
+ }
1563
+ case "INTENT_COMPLETED": {
1564
+ const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
1565
+ if (intentStep) {
1566
+ intentStep.status = "completed";
1567
+ intentStep.isThinking = false;
1568
+ if (event.elapsedMs) intentStep.elapsedMs = event.elapsedMs;
1569
+ if (intentStep.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
1570
+ }
1571
+ state.lastEventType = eventType;
1572
+ break;
1573
+ }
1574
+ case "AGGREGATOR_THINKING": {
1575
+ addThinkingLine(state, "**Finalizing**", event.message || "Preparing response...");
1576
+ const stepId = `step-${state.stepCounter++}`;
1577
+ state.steps.push({
1578
+ id: stepId,
1579
+ eventType,
1580
+ message,
1581
+ status: "in_progress",
1582
+ timestamp: Date.now(),
1583
+ elapsedMs: event.elapsedMs
1584
+ });
1585
+ state.currentExecutingStepId = stepId;
1586
+ state.lastEventType = eventType;
1587
+ break;
1588
+ }
1589
+ case "AGGREGATOR_COMPLETED": {
1590
+ appendThinkingText(state, "\n" + (event.message || "Response ready"));
1591
+ const step = state.steps.find((s) => s.eventType === "AGGREGATOR_THINKING" && s.status === "in_progress");
1592
+ if (step) {
1593
+ step.status = "completed";
1594
+ if (event.elapsedMs) step.elapsedMs = event.elapsedMs;
1595
+ if (step.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
1596
+ }
1597
+ state.lastEventType = eventType;
1598
+ break;
1599
+ }
1600
+ case "WORKFLOW_COMPLETED":
1601
+ case "COMPLETED": {
1602
+ let content = extractResponseContent(event.response);
1603
+ const trace = event.trace && typeof event.trace === "object" ? event.trace : null;
1604
+ if (!content && trace?.workflowMsg && typeof trace.workflowMsg === "string") {
1605
+ content = trace.workflowMsg;
1606
+ }
1607
+ if (!content && trace?.aggregator && typeof trace.aggregator === "object") {
1608
+ const agg = trace.aggregator;
1609
+ if (typeof agg.response === "string") content = agg.response;
1610
+ else content = extractResponseContent(agg.response);
1611
+ }
1612
+ if (content) {
1613
+ state.finalResponse = content;
1614
+ state.finalData = event.response ?? event.trace;
1615
+ state.hasError = false;
1616
+ state.errorMessage = "";
1617
+ } else {
1618
+ state.hasError = true;
1619
+ state.errorMessage = "WORKFLOW_FAILED";
1620
+ }
1621
+ state.steps.forEach((step) => {
1622
+ if (step.status === "in_progress") {
1623
+ step.status = "completed";
1624
+ step.isThinking = false;
1625
+ }
1626
+ });
1627
+ state.lastEventType = eventType;
1628
+ break;
1629
+ }
1630
+ case "USER_ACTION_REQUIRED": {
1631
+ completeLastInProgressStep2(state.steps);
1632
+ if (event.userActionRequest) {
1633
+ state.userActionRequest = {
1634
+ userActionId: event.userActionRequest.userActionId,
1635
+ userActionType: event.userActionRequest.userActionType,
1636
+ message: event.userActionRequest.message,
1637
+ requestedSchema: event.userActionRequest.requestedSchema,
1638
+ metadata: event.userActionRequest.metadata
1639
+ };
1640
+ }
1641
+ state.userActionPending = true;
1642
+ const req = event.userActionRequest;
1643
+ if (req) {
1644
+ addThinkingLine(state, "**Verification Required**", req.message || "Waiting for authorization...");
1645
+ }
1646
+ const stepId = `step-${state.stepCounter++}`;
1647
+ state.steps.push({
1648
+ id: stepId,
1649
+ eventType,
1650
+ message,
1651
+ status: "in_progress",
1652
+ timestamp: Date.now(),
1653
+ elapsedMs: event.elapsedMs
1654
+ });
1655
+ state.currentExecutingStepId = stepId;
1656
+ state.lastEventType = eventType;
1657
+ break;
1658
+ }
1659
+ case "USER_ACTION_SUCCESS": {
1660
+ appendThinkingText(state, "\n\u2713 " + (event.message || "Verification successful"));
1661
+ completeLastInProgressStep2(state.steps);
1662
+ state.userActionRequest = void 0;
1663
+ state.userActionPending = false;
1664
+ state.userActionResult = "approved";
1665
+ const stepId = `step-${state.stepCounter++}`;
1666
+ state.steps.push({
1667
+ id: stepId,
1668
+ eventType,
1669
+ message,
1670
+ status: "completed",
1671
+ timestamp: Date.now(),
1672
+ elapsedMs: event.elapsedMs
1673
+ });
1674
+ state.lastEventType = eventType;
1675
+ break;
1676
+ }
1677
+ case "USER_ACTION_INVALID": {
1678
+ completeLastInProgressStep2(state.steps);
1679
+ const errorStepId = `step-${state.stepCounter++}`;
1680
+ state.steps.push({
1681
+ id: errorStepId,
1682
+ eventType,
1683
+ message,
1684
+ status: "error",
1685
+ timestamp: Date.now(),
1686
+ elapsedMs: event.elapsedMs
1687
+ });
1688
+ const retryStepId = `step-${state.stepCounter++}`;
1689
+ state.steps.push({
1690
+ id: retryStepId,
1691
+ eventType: "USER_ACTION_REQUIRED",
1692
+ message: "Waiting for verification...",
1693
+ status: "in_progress",
1694
+ timestamp: Date.now()
1695
+ });
1696
+ state.currentExecutingStepId = retryStepId;
1697
+ state.lastEventType = eventType;
1698
+ break;
1699
+ }
1700
+ case "USER_ACTION_REJECTED": {
1701
+ appendThinkingText(state, "\n\u2717 " + (event.message || "Verification rejected"));
1702
+ completeLastInProgressStep2(state.steps);
1703
+ state.userActionRequest = void 0;
1704
+ state.userActionPending = false;
1705
+ state.userActionResult = "rejected";
1706
+ const stepId = `step-${state.stepCounter++}`;
1707
+ state.steps.push({
1708
+ id: stepId,
1709
+ eventType,
1710
+ message,
1711
+ status: "completed",
1712
+ timestamp: Date.now(),
1713
+ elapsedMs: event.elapsedMs
1714
+ });
1715
+ state.lastEventType = eventType;
1716
+ break;
1717
+ }
1718
+ case "USER_ACTION_EXPIRED": {
1719
+ appendThinkingText(state, "\n\u2717 " + (event.message || "Verification expired"));
1720
+ completeLastInProgressStep2(state.steps);
1721
+ state.userActionRequest = void 0;
1722
+ state.userActionPending = false;
1723
+ const stepId = `step-${state.stepCounter++}`;
1724
+ state.steps.push({
1725
+ id: stepId,
1726
+ eventType,
1727
+ message,
1728
+ status: "error",
1729
+ timestamp: Date.now(),
1730
+ elapsedMs: event.elapsedMs
1731
+ });
1732
+ state.lastEventType = eventType;
1733
+ break;
1734
+ }
1735
+ case "USER_ACTION_RESENT": {
1736
+ const stepId = `step-${state.stepCounter++}`;
1737
+ state.steps.push({
1738
+ id: stepId,
1739
+ eventType,
1740
+ message,
1741
+ status: "completed",
1742
+ timestamp: Date.now(),
1743
+ elapsedMs: event.elapsedMs
1744
+ });
1745
+ state.lastEventType = eventType;
1746
+ break;
1747
+ }
1748
+ case "USER_ACTION_FAILED": {
1749
+ appendThinkingText(state, "\n\u2717 " + (event.message || "Verification failed"));
1750
+ completeLastInProgressStep2(state.steps);
1751
+ state.userActionRequest = void 0;
1752
+ state.userActionPending = false;
1753
+ const stepId = `step-${state.stepCounter++}`;
1754
+ state.steps.push({
1755
+ id: stepId,
1756
+ eventType,
1757
+ message,
1758
+ status: "error",
1759
+ timestamp: Date.now(),
1760
+ elapsedMs: event.elapsedMs
1761
+ });
1762
+ state.lastEventType = eventType;
1763
+ break;
1764
+ }
1765
+ case "WORKFLOW_ERROR":
1766
+ case "ERROR":
1767
+ state.hasError = true;
1768
+ state.errorMessage = event.errorMessage || event.message || "Workflow error";
1769
+ state.lastEventType = eventType;
1770
+ break;
1771
+ case "INTENT_ERROR": {
1772
+ state.errorMessage = message || event.errorMessage || "An error occurred";
1773
+ const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
1774
+ if (intentStep) {
1775
+ intentStep.status = "error";
1776
+ intentStep.isThinking = false;
1777
+ }
1778
+ state.lastEventType = eventType;
1779
+ break;
1780
+ }
1781
+ default:
1782
+ state.lastEventType = eventType;
1783
+ break;
1784
+ }
1785
+ return state;
1786
+ }
1787
+
1788
+ // src/hooks/useStreamManagerV2.ts
1789
+ var FRIENDLY_ERROR_MESSAGE2 = "Oops, something went wrong. Please try again.";
1790
+ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForResponse) {
1791
+ const abortControllerRef = react.useRef(null);
1792
+ const configRef = react.useRef(config);
1793
+ configRef.current = config;
1794
+ const callbacksRef = react.useRef(callbacks);
1795
+ callbacksRef.current = callbacks;
1796
+ const startStream = react.useCallback(
1797
+ async (userMessage, streamingId, sessionId, externalAbortController) => {
1798
+ abortControllerRef.current?.abort();
1799
+ const abortController = externalAbortController ?? new AbortController();
1800
+ abortControllerRef.current = abortController;
1801
+ const state = createInitialV2State();
1802
+ const updateMessage = (update) => {
1803
+ if (abortController.signal.aborted) return;
1804
+ setMessages(
1805
+ (prev) => prev.map(
1806
+ (msg) => msg.id === streamingId ? { ...msg, ...update } : msg
1807
+ )
1808
+ );
1809
+ };
1810
+ const currentConfig = configRef.current;
1811
+ const requestBody = buildRequestBody(currentConfig, userMessage, sessionId);
1812
+ const url = buildStreamingUrl(currentConfig);
1813
+ const headers = buildRequestHeaders(currentConfig);
1814
+ try {
1815
+ await streamWorkflowEvents(url, requestBody, headers, {
1816
+ signal: abortController.signal,
1817
+ onEvent: (event) => {
1818
+ if (abortController.signal.aborted) return;
1819
+ if (typeof event.eventType === "string" && event.eventType.toUpperCase() === "KEEP_ALIVE") {
1820
+ if (event.executionId) state.executionId = event.executionId;
1821
+ if (event.sessionId) state.sessionId = event.sessionId;
1822
+ return;
1823
+ }
1824
+ processStreamEventV2(event, state);
1825
+ const eventType = event.eventType;
1826
+ if (eventType === "USER_ACTION_REQUIRED" && state.userActionRequest) {
1827
+ callbacksRef.current.onUserActionRequired?.(state.userActionRequest);
1828
+ } else if (eventType.startsWith("USER_ACTION_") && eventType !== "USER_ACTION_REQUIRED") {
1829
+ const msg = event.message?.trim() || event.errorMessage?.trim() || getEventMessage(event);
1830
+ callbacksRef.current.onUserActionEvent?.(eventType, msg);
1831
+ }
1832
+ const activeStep = state.steps.find((s) => s.id === state.currentExecutingStepId);
1833
+ const lastInProgressStep = [...state.steps].reverse().find((s) => s.status === "in_progress");
1834
+ const currentMessage = activeStep?.message || lastInProgressStep?.message || getEventMessage(event);
1835
+ if (state.hasError) {
1836
+ updateMessage({
1837
+ streamingContent: FRIENDLY_ERROR_MESSAGE2,
1838
+ content: FRIENDLY_ERROR_MESSAGE2,
1839
+ streamProgress: "error",
1840
+ isError: true,
1841
+ errorDetails: state.errorMessage,
1842
+ formattedThinkingText: state.formattedThinkingText || void 0,
1843
+ steps: [...state.steps],
1844
+ currentExecutingStepId: void 0,
1845
+ executionId: state.executionId,
1846
+ sessionId: state.sessionId
1847
+ });
1848
+ } else {
1849
+ updateMessage({
1850
+ streamingContent: "",
1851
+ content: "",
1852
+ currentMessage,
1853
+ streamProgress: "processing",
1854
+ isError: false,
1855
+ formattedThinkingText: state.formattedThinkingText || void 0,
1856
+ steps: [...state.steps],
1857
+ currentExecutingStepId: state.currentExecutingStepId,
1858
+ executionId: state.executionId,
1859
+ sessionId: state.sessionId,
1860
+ userActionResult: state.userActionResult,
1861
+ isCancelled: false
1862
+ });
1863
+ }
1864
+ },
1865
+ onError: (error) => {
1866
+ setIsWaitingForResponse(false);
1867
+ if (error.name !== "AbortError") {
1868
+ callbacksRef.current.onError?.(error);
1869
+ }
1870
+ if (state.userActionPending) {
1871
+ state.userActionPending = false;
1872
+ state.userActionRequest = void 0;
1873
+ callbacksRef.current.onUserActionEvent?.(
1874
+ "USER_ACTION_FAILED",
1875
+ "Connection lost. Please try again."
1876
+ );
1877
+ }
1878
+ const isAborted = error.name === "AbortError";
1879
+ setMessages(
1880
+ (prev) => prev.map(
1881
+ (msg) => msg.id === streamingId ? {
1882
+ ...msg,
1883
+ isStreaming: false,
1884
+ streamProgress: isAborted ? "processing" : "error",
1885
+ isError: !isAborted,
1886
+ isCancelled: isAborted,
1887
+ errorDetails: isAborted ? void 0 : error.message,
1888
+ content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE2,
1889
+ currentMessage: isAborted ? "Thinking..." : void 0,
1890
+ formattedThinkingText: state.formattedThinkingText || void 0,
1891
+ steps: [...state.steps].map((step) => {
1892
+ if (step.status === "in_progress" && isAborted) {
1893
+ return { ...step, status: "pending" };
1894
+ }
1895
+ return step;
1896
+ }),
1897
+ currentExecutingStepId: void 0
1898
+ } : msg
1899
+ )
1900
+ );
1901
+ },
1902
+ onComplete: () => {
1903
+ setIsWaitingForResponse(false);
1904
+ if (state.userActionPending) {
1905
+ state.userActionPending = false;
1906
+ state.userActionRequest = void 0;
1907
+ callbacksRef.current.onUserActionEvent?.(
1908
+ "USER_ACTION_FAILED",
1909
+ "Verification could not be completed."
1910
+ );
1911
+ }
1912
+ if (state.sessionId && state.sessionId !== sessionId) {
1913
+ callbacksRef.current.onSessionIdChange?.(state.sessionId);
1914
+ }
1915
+ const needsImageResolve = !state.hasError && !abortController.signal.aborted && hasRagImages(state.finalResponse);
1916
+ const finalMessage = {
1917
+ id: streamingId,
1918
+ sessionId: state.sessionId || sessionId,
1919
+ role: "assistant",
1920
+ content: state.hasError ? FRIENDLY_ERROR_MESSAGE2 : state.finalResponse || "",
1921
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1922
+ isStreaming: false,
1923
+ streamProgress: state.hasError ? "error" : "completed",
1924
+ isError: state.hasError,
1925
+ errorDetails: state.hasError ? state.errorMessage : void 0,
1926
+ executionId: state.executionId,
1927
+ tracingData: state.finalData,
1928
+ steps: state.hasError ? [] : [...state.steps],
1929
+ isCancelled: false,
1930
+ currentExecutingStepId: void 0,
1931
+ userActionResult: state.userActionResult,
1932
+ formattedThinkingText: state.hasError ? void 0 : state.formattedThinkingText || void 0,
1933
+ isResolvingImages: needsImageResolve
1934
+ };
1935
+ setMessages(
1936
+ (prev) => prev.map(
1937
+ (msg) => msg.id === streamingId ? finalMessage : msg
1938
+ )
1939
+ );
1940
+ callbacksRef.current.onStreamComplete?.(finalMessage);
1941
+ }
1942
+ });
1943
+ const shouldResolveImages = !abortController.signal.aborted && !state.hasError && hasRagImages(state.finalResponse);
1944
+ if (shouldResolveImages) {
1945
+ await waitForNextPaint(abortController.signal);
1946
+ }
1947
+ if (shouldResolveImages && !abortController.signal.aborted) {
1948
+ try {
1949
+ const resolvedContent = await resolveRagImageUrls(
1950
+ currentConfig,
1951
+ state.finalResponse,
1952
+ abortController.signal
1953
+ );
1954
+ setMessages(
1955
+ (prev) => prev.map(
1956
+ (msg) => msg.id === streamingId ? { ...msg, content: resolvedContent, isResolvingImages: false } : msg
1957
+ )
1958
+ );
1959
+ } catch {
1960
+ setMessages(
1961
+ (prev) => prev.map(
1962
+ (msg) => msg.id === streamingId ? { ...msg, isResolvingImages: false } : msg
1963
+ )
1964
+ );
1965
+ }
1966
+ }
1967
+ return state.sessionId;
1968
+ } catch (error) {
1969
+ setIsWaitingForResponse(false);
1970
+ if (error.name !== "AbortError") {
1971
+ callbacksRef.current.onError?.(error);
1972
+ }
1973
+ if (state.userActionPending) {
1974
+ state.userActionPending = false;
1975
+ state.userActionRequest = void 0;
1976
+ callbacksRef.current.onUserActionEvent?.(
1977
+ "USER_ACTION_FAILED",
1978
+ "Connection lost. Please try again."
1979
+ );
1980
+ }
1981
+ const isAborted = error.name === "AbortError";
1982
+ setMessages(
1983
+ (prev) => prev.map(
1984
+ (msg) => msg.id === streamingId ? {
1985
+ ...msg,
1986
+ isStreaming: false,
1987
+ streamProgress: isAborted ? "processing" : "error",
1988
+ isError: !isAborted,
1989
+ isCancelled: isAborted,
1990
+ errorDetails: isAborted ? void 0 : error.message,
1991
+ content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE2,
1992
+ formattedThinkingText: state.formattedThinkingText || void 0,
1993
+ steps: [...state.steps].map((step) => {
1994
+ if (step.status === "in_progress" && isAborted) {
1995
+ return { ...step, status: "pending" };
1996
+ }
1997
+ return step;
1998
+ }),
1999
+ currentExecutingStepId: void 0
2000
+ } : msg
2001
+ )
2002
+ );
2003
+ return state.sessionId;
2004
+ }
2005
+ },
2006
+ [setMessages, setIsWaitingForResponse]
2007
+ );
2008
+ const cancelStream = react.useCallback(() => {
2009
+ abortControllerRef.current?.abort();
2010
+ }, []);
2011
+ return {
2012
+ startStream,
2013
+ cancelStream,
2014
+ abortControllerRef
2015
+ };
2016
+ }
2017
+
2018
+ // src/hooks/useChatV2.ts
2019
+ function useChatV2(config, callbacks = {}) {
2020
+ const [messages, setMessages] = react.useState(() => {
2021
+ if (config.userId) return chatStore.get(config.userId);
2022
+ return config.initialMessages ?? [];
2023
+ });
2024
+ const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(false);
2025
+ const sessionIdRef = react.useRef(
2026
+ config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
2027
+ );
2028
+ const prevUserIdRef = react.useRef(config.userId);
2029
+ const callbacksRef = react.useRef(callbacks);
2030
+ callbacksRef.current = callbacks;
2031
+ const configRef = react.useRef(config);
2032
+ configRef.current = config;
2033
+ const messagesRef = react.useRef(messages);
2034
+ messagesRef.current = messages;
2035
+ const storeAwareSetMessages = react.useCallback(
2036
+ (updater) => {
2037
+ const { userId } = configRef.current;
2038
+ if (userId && activeStreamStore.has(userId)) {
2039
+ activeStreamStore.applyMessages(userId, updater);
2040
+ }
2041
+ setMessages(updater);
2042
+ },
2043
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2044
+ []
2045
+ );
2046
+ const storeAwareSetIsWaiting = react.useCallback(
2047
+ (waiting) => {
2048
+ const { userId } = configRef.current;
2049
+ if (userId && activeStreamStore.has(userId)) {
2050
+ activeStreamStore.setWaiting(userId, waiting);
2051
+ }
2052
+ setIsWaitingForResponse(waiting);
2053
+ },
2054
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2055
+ []
2056
+ );
2057
+ const [userActionState, setUserActionState] = react.useState({
2058
+ request: null,
2059
+ result: null,
2060
+ clearOtpTrigger: 0
2061
+ });
2062
+ const userActionStateRef = react.useRef(userActionState);
2063
+ userActionStateRef.current = userActionState;
2064
+ const wrappedCallbacks = react.useMemo(() => ({
2065
+ ...callbacksRef.current,
2066
+ onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
2067
+ onStreamStart: () => callbacksRef.current.onStreamStart?.(),
2068
+ onStreamComplete: (message) => callbacksRef.current.onStreamComplete?.(message),
2069
+ onError: (error) => callbacksRef.current.onError?.(error),
2070
+ onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
2071
+ onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
2072
+ onUserActionRequired: (request) => {
2073
+ setUserActionState((prev) => ({ ...prev, request, result: null }));
2074
+ callbacksRef.current.onUserActionRequired?.(request);
2075
+ },
2076
+ onUserActionEvent: (eventType, message) => {
2077
+ switch (eventType) {
2078
+ case "USER_ACTION_SUCCESS":
2079
+ setUserActionState((prev) => ({ ...prev, request: null, result: "approved" }));
2080
+ break;
2081
+ case "USER_ACTION_REJECTED":
2082
+ setUserActionState((prev) => ({ ...prev, request: null, result: "rejected" }));
2083
+ break;
2084
+ case "USER_ACTION_EXPIRED":
2085
+ case "USER_ACTION_FAILED":
2086
+ setUserActionState((prev) => ({ ...prev, request: null }));
2087
+ break;
2088
+ case "USER_ACTION_INVALID":
2089
+ setUserActionState((prev) => ({ ...prev, clearOtpTrigger: prev.clearOtpTrigger + 1 }));
2090
+ break;
2091
+ }
2092
+ callbacksRef.current.onUserActionEvent?.(eventType, message);
2093
+ }
2094
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2095
+ }), []);
2096
+ const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManagerV2(
2097
+ config,
2098
+ wrappedCallbacks,
2099
+ storeAwareSetMessages,
2100
+ storeAwareSetIsWaiting
2101
+ );
2102
+ const sendMessage = react.useCallback(
2103
+ async (userMessage) => {
2104
+ if (!userMessage.trim()) return;
2105
+ if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
2106
+ sessionIdRef.current = generateId();
2107
+ callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
2108
+ }
2109
+ const userMessageId = `user-${Date.now()}`;
2110
+ const userMsg = {
2111
+ id: userMessageId,
2112
+ sessionId: sessionIdRef.current,
2113
+ role: "user",
2114
+ content: userMessage,
2115
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2116
+ };
2117
+ setMessages((prev) => [...prev, userMsg]);
2118
+ callbacksRef.current.onMessageSent?.(userMessage);
2119
+ setIsWaitingForResponse(true);
2120
+ callbacksRef.current.onStreamStart?.();
2121
+ const streamingId = `assistant-${Date.now()}`;
2122
+ const streamingMsg = {
2123
+ id: streamingId,
2124
+ sessionId: sessionIdRef.current,
2125
+ role: "assistant",
2126
+ content: "",
2127
+ streamingContent: "",
2128
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2129
+ isStreaming: true,
2130
+ streamProgress: "started",
2131
+ steps: [],
2132
+ currentExecutingStepId: void 0,
2133
+ isCancelled: false,
2134
+ currentMessage: void 0
2135
+ };
2136
+ setMessages((prev) => [...prev, streamingMsg]);
2137
+ const abortController = new AbortController();
2138
+ const { userId } = configRef.current;
2139
+ if (userId) {
2140
+ const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
2141
+ activeStreamStore.start(userId, abortController, initialMessages);
2142
+ }
2143
+ const newSessionId = await startStream(
2144
+ userMessage,
2145
+ streamingId,
2146
+ sessionIdRef.current,
2147
+ abortController
2148
+ );
2149
+ if (userId) {
2150
+ activeStreamStore.complete(userId);
2151
+ }
2152
+ if (!abortController.signal.aborted && newSessionId && newSessionId !== sessionIdRef.current) {
2153
+ sessionIdRef.current = newSessionId;
2154
+ }
2155
+ },
2156
+ [startStream]
2157
+ );
2158
+ const clearMessages = react.useCallback(() => {
2159
+ if (configRef.current.userId) {
2160
+ chatStore.delete(configRef.current.userId);
2161
+ }
2162
+ setMessages([]);
2163
+ }, []);
2164
+ const prependMessages = react.useCallback((msgs) => {
2165
+ setMessages((prev) => [...msgs, ...prev]);
2166
+ }, []);
2167
+ const cancelStream = react.useCallback(() => {
2168
+ if (configRef.current.userId) {
2169
+ activeStreamStore.abort(configRef.current.userId);
2170
+ }
2171
+ cancelStreamManager();
2172
+ setIsWaitingForResponse(false);
2173
+ setUserActionState((prev) => ({ ...prev, request: null, result: null }));
2174
+ setMessages(
2175
+ (prev) => prev.map((msg) => {
2176
+ if (msg.isStreaming) {
2177
+ return {
2178
+ ...msg,
2179
+ ...createCancelledMessageUpdate(
2180
+ msg.steps || [],
2181
+ msg.currentMessage
2182
+ )
2183
+ };
2184
+ }
2185
+ return msg;
2186
+ })
2187
+ );
2188
+ }, [cancelStreamManager]);
2189
+ const resetSession = react.useCallback(() => {
2190
+ if (configRef.current.userId) {
2191
+ activeStreamStore.abort(configRef.current.userId);
2192
+ chatStore.delete(configRef.current.userId);
2193
+ }
2194
+ setMessages([]);
2195
+ sessionIdRef.current = void 0;
2196
+ abortControllerRef.current?.abort();
2197
+ setIsWaitingForResponse(false);
2198
+ setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
2199
+ }, []);
2200
+ const getSessionId = react.useCallback(() => {
2201
+ return sessionIdRef.current;
2202
+ }, []);
2203
+ const getMessages = react.useCallback(() => {
2204
+ return messages;
2205
+ }, [messages]);
2206
+ const approveUserAction = react.useCallback(
2207
+ async (otp) => {
2208
+ const request = userActionStateRef.current.request;
2209
+ if (!request) return;
2210
+ try {
2211
+ await submitUserAction(configRef.current, request.userActionId, { otp });
2212
+ } catch (error) {
2213
+ setUserActionState((prev) => ({
2214
+ ...prev,
2215
+ clearOtpTrigger: prev.clearOtpTrigger + 1
2216
+ }));
2217
+ callbacksRef.current.onError?.(error);
2218
+ throw error;
2219
+ }
2220
+ },
2221
+ []
2222
+ );
2223
+ const rejectUserAction = react.useCallback(async () => {
2224
+ const request = userActionStateRef.current.request;
2225
+ if (!request) return;
2226
+ try {
2227
+ setMessages((prev) => {
2228
+ let lastStreamingIdx = -1;
2229
+ for (let i = prev.length - 1; i >= 0; i--) {
2230
+ if (prev[i].role === "assistant" && prev[i].isStreaming) {
2231
+ lastStreamingIdx = i;
2232
+ break;
2233
+ }
2234
+ }
2235
+ if (lastStreamingIdx === -1) return prev;
2236
+ return prev.map(
2237
+ (msg, i) => i === lastStreamingIdx ? { ...msg, currentMessage: "Rejecting..." } : msg
2238
+ );
2239
+ });
2240
+ await cancelUserAction(configRef.current, request.userActionId);
2241
+ } catch (error) {
2242
+ callbacksRef.current.onError?.(error);
2243
+ throw error;
2244
+ }
2245
+ }, []);
2246
+ const resendOtp = react.useCallback(async () => {
2247
+ const request = userActionStateRef.current.request;
2248
+ if (!request) return;
2249
+ try {
2250
+ await resendUserAction(configRef.current, request.userActionId);
2251
+ } catch (error) {
2252
+ callbacksRef.current.onError?.(error);
2253
+ throw error;
2254
+ }
2255
+ }, []);
2256
+ react.useEffect(() => {
2257
+ const { userId } = config;
2258
+ if (!userId) return;
2259
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
2260
+ setMessages(msgs);
2261
+ setIsWaitingForResponse(isWaiting);
2262
+ });
2263
+ const active = activeStreamStore.get(userId);
2264
+ if (active) {
2265
+ setMessages(active.messages);
2266
+ setIsWaitingForResponse(active.isWaiting);
2267
+ }
2268
+ return unsubscribe;
2269
+ }, []);
2270
+ react.useEffect(() => {
2271
+ if (!config.userId) return;
2272
+ const toSave = messages.filter((m) => !m.isStreaming);
2273
+ if (toSave.length > 0) {
2274
+ chatStore.set(config.userId, toSave);
2275
+ }
2276
+ }, [messages, config.userId]);
2277
+ react.useEffect(() => {
2278
+ const prevUserId = prevUserIdRef.current;
2279
+ prevUserIdRef.current = config.userId;
2280
+ if (prevUserId === config.userId) return;
2281
+ if (prevUserId && !config.userId) {
2282
+ chatStore.delete(prevUserId);
2283
+ setMessages([]);
2284
+ sessionIdRef.current = void 0;
2285
+ setIsWaitingForResponse(false);
2286
+ setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
2287
+ } else if (config.userId) {
2288
+ const stored = chatStore.get(config.userId);
2289
+ setMessages(stored);
2290
+ sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
2291
+ }
2292
+ }, [config.userId]);
2293
+ return {
2294
+ messages,
2295
+ sendMessage,
2296
+ clearMessages,
2297
+ prependMessages,
2298
+ cancelStream,
2299
+ resetSession,
2300
+ getSessionId,
2301
+ getMessages,
2302
+ isWaitingForResponse,
2303
+ sessionId: sessionIdRef.current,
2304
+ userActionState,
2305
+ approveUserAction,
2306
+ rejectUserAction,
2307
+ resendOtp
2308
+ };
2309
+ }
1241
2310
  function useVoice() {
1242
2311
  const [voiceState, setVoiceState] = react.useState("idle");
1243
2312
  const [transcribedText, setTranscribedText] = react.useState("");
@@ -1354,12 +2423,16 @@ function useVoice() {
1354
2423
  };
1355
2424
  }
1356
2425
 
2426
+ exports.buildFormattedThinking = buildFormattedThinking;
1357
2427
  exports.cancelUserAction = cancelUserAction;
2428
+ exports.createInitialV2State = createInitialV2State;
1358
2429
  exports.generateId = generateId;
2430
+ exports.processStreamEventV2 = processStreamEventV2;
1359
2431
  exports.resendUserAction = resendUserAction;
1360
2432
  exports.streamWorkflowEvents = streamWorkflowEvents;
1361
2433
  exports.submitUserAction = submitUserAction;
1362
2434
  exports.useChat = useChat;
2435
+ exports.useChatV2 = useChatV2;
1363
2436
  exports.useVoice = useVoice;
1364
2437
  //# sourceMappingURL=index.native.js.map
1365
2438
  //# sourceMappingURL=index.native.js.map