@paymanai/payman-typescript-ask-sdk 1.2.9 → 1.2.11

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.
@@ -194,6 +194,14 @@ function getEventMessage(event) {
194
194
  return eventType;
195
195
  }
196
196
  }
197
+ function workingPhaseDetailForDisplay(raw) {
198
+ const t = raw.trim();
199
+ if (!t) return "";
200
+ if (/^Identified\s+\d+\s+tasks?\s+to\s+execute\.?$/i.test(t)) {
201
+ return "";
202
+ }
203
+ return t;
204
+ }
197
205
  function extractResponseContent(response) {
198
206
  if (typeof response === "string") {
199
207
  return response;
@@ -500,8 +508,84 @@ function processStreamEvent(event, state) {
500
508
 
501
509
  // src/utils/messageStateManager.ts
502
510
  var FRIENDLY_ERROR_MESSAGE = "Oops, something went wrong. Please try again.";
511
+ function buildFormattedThinking(steps, allThinkingText) {
512
+ const parts = [];
513
+ const safeSteps = steps ?? [];
514
+ const cleanAll = allThinkingText.replace(/^\s+/, "");
515
+ if (cleanAll) {
516
+ const firstStepWithThinking = safeSteps.find(
517
+ (s) => s.thinkingText && s.thinkingText.trim()
518
+ );
519
+ if (!firstStepWithThinking) {
520
+ parts.push("**Preflight**");
521
+ parts.push(cleanAll);
522
+ } else {
523
+ const stepText = firstStepWithThinking.thinkingText.trim();
524
+ const idx = cleanAll.indexOf(stepText);
525
+ if (idx > 0) {
526
+ const orphaned = cleanAll.substring(0, idx).replace(/\s+$/, "");
527
+ if (orphaned) {
528
+ parts.push("**Preflight**");
529
+ parts.push(orphaned);
530
+ }
531
+ }
532
+ }
533
+ }
534
+ for (const step of safeSteps) {
535
+ switch (step.eventType) {
536
+ case "ORCHESTRATOR_THINKING":
537
+ parts.push("**Planning**");
538
+ if (step.message) parts.push(step.message);
539
+ break;
540
+ case "WORKING": {
541
+ const detail = workingPhaseDetailForDisplay(step.message || "");
542
+ parts.push("**Working**");
543
+ if (detail) parts.push(detail);
544
+ break;
545
+ }
546
+ case "INTENT_STARTED": {
547
+ let label = step.message || "Processing";
548
+ const started = label.match(/^(.+?)\s+started$/i);
549
+ const progress = label.match(/^(.+?)\s+in progress$/i);
550
+ if (started) label = started[1];
551
+ else if (progress) label = progress[1];
552
+ parts.push(`**${label}**`);
553
+ if (step.thinkingText) parts.push(step.thinkingText);
554
+ break;
555
+ }
556
+ case "INTENT_PROGRESS": {
557
+ if (step.thinkingText) parts.push(step.thinkingText);
558
+ else if (step.message) parts.push(step.message);
559
+ break;
560
+ }
561
+ case "AGGREGATOR_THINKING":
562
+ parts.push("**Finalizing**");
563
+ if (step.message) parts.push(step.message);
564
+ break;
565
+ case "USER_ACTION_REQUIRED":
566
+ parts.push("**Verification Required**");
567
+ if (step.message) parts.push(step.message);
568
+ break;
569
+ case "USER_ACTION_SUCCESS":
570
+ parts.push(`\u2713 ${step.message || "Verification successful"}`);
571
+ break;
572
+ case "USER_ACTION_REJECTED":
573
+ parts.push(`\u2717 ${step.message || "Verification rejected"}`);
574
+ break;
575
+ case "USER_ACTION_EXPIRED":
576
+ parts.push(`\u2717 ${step.message || "Verification expired"}`);
577
+ break;
578
+ case "USER_ACTION_FAILED":
579
+ parts.push(`\u2717 ${step.message || "Verification failed"}`);
580
+ break;
581
+ }
582
+ }
583
+ return parts.length > 0 ? parts.join("\n") : allThinkingText;
584
+ }
503
585
  function createStreamingMessageUpdate(state) {
504
586
  const hasCompletedContent = state.accumulatedContent && state.finalData !== void 0;
587
+ const steps = state.hasError ? [] : [...state.steps];
588
+ const allThinking = state.hasError ? void 0 : state.allThinkingText;
505
589
  return {
506
590
  streamingContent: state.hasError ? FRIENDLY_ERROR_MESSAGE : hasCompletedContent ? state.accumulatedContent : "",
507
591
  content: state.hasError ? FRIENDLY_ERROR_MESSAGE : "",
@@ -511,12 +595,13 @@ function createStreamingMessageUpdate(state) {
511
595
  errorDetails: state.hasError ? state.errorMessage : void 0,
512
596
  executionId: state.executionId,
513
597
  sessionId: state.sessionId,
514
- steps: state.hasError ? [] : [...state.steps],
598
+ steps,
515
599
  currentExecutingStepId: state.hasError ? void 0 : state.currentExecutingStepId,
516
600
  isCancelled: false,
517
601
  userActionResult: state.userActionResult,
518
602
  activeThinkingText: state.hasError ? void 0 : state.activeThinkingText,
519
- allThinkingText: state.hasError ? void 0 : state.allThinkingText
603
+ allThinkingText: allThinking,
604
+ formattedThinkingText: state.hasError ? void 0 : buildFormattedThinking(steps, allThinking || "")
520
605
  };
521
606
  }
522
607
  function createErrorMessageUpdate(error, state) {
@@ -540,6 +625,8 @@ function createErrorMessageUpdate(error, state) {
540
625
  };
541
626
  }
542
627
  function createFinalMessage(streamingId, state) {
628
+ const steps = state.hasError ? [] : [...state.steps];
629
+ const allThinking = state.hasError ? void 0 : state.allThinkingText;
543
630
  return {
544
631
  id: streamingId,
545
632
  sessionId: state.sessionId,
@@ -552,12 +639,13 @@ function createFinalMessage(streamingId, state) {
552
639
  errorDetails: state.hasError ? state.errorMessage : void 0,
553
640
  executionId: state.executionId,
554
641
  tracingData: state.finalData,
555
- steps: state.hasError ? [] : [...state.steps],
642
+ steps,
556
643
  isCancelled: false,
557
644
  currentExecutingStepId: void 0,
558
645
  userActionResult: state.userActionResult,
559
646
  activeThinkingText: void 0,
560
- allThinkingText: state.hasError ? void 0 : state.allThinkingText,
647
+ allThinkingText: allThinking,
648
+ formattedThinkingText: state.hasError ? void 0 : buildFormattedThinking(steps, allThinking || ""),
561
649
  isResolvingImages: state.hasError ? void 0 : state.isResolvingImages
562
650
  };
563
651
  }
@@ -1327,6 +1415,924 @@ function useChat(config, callbacks = {}) {
1327
1415
  resendOtp
1328
1416
  };
1329
1417
  }
1418
+
1419
+ // src/utils/v2EventProcessor.ts
1420
+ function getEventText(event, field) {
1421
+ const value = event[field];
1422
+ return typeof value === "string" ? value.trim() : "";
1423
+ }
1424
+ function shouldShowIntentHeader(event) {
1425
+ const workerName = getEventText(event, "workerName");
1426
+ const intentId = getEventText(event, "intentId");
1427
+ return Boolean(workerName && intentId && workerName === intentId);
1428
+ }
1429
+ function addThinkingHeader(state, header) {
1430
+ state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + header;
1431
+ }
1432
+ function addThinkingDetail(state, detail) {
1433
+ const trimmed = detail.trim();
1434
+ if (!trimmed) return;
1435
+ state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + trimmed;
1436
+ }
1437
+ function addThinkingLine(state, header, detail) {
1438
+ state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + header + "\n" + detail;
1439
+ }
1440
+ function appendThinkingText(state, text) {
1441
+ state.formattedThinkingText += text;
1442
+ }
1443
+ function completeLastInProgressStep2(steps) {
1444
+ for (let i = steps.length - 1; i >= 0; i--) {
1445
+ if (steps[i].status === "in_progress") {
1446
+ steps[i].status = "completed";
1447
+ return;
1448
+ }
1449
+ }
1450
+ }
1451
+ function createInitialV2State() {
1452
+ return {
1453
+ formattedThinkingText: "",
1454
+ finalResponse: "",
1455
+ currentWorker: "",
1456
+ lastEventType: "",
1457
+ sessionId: void 0,
1458
+ executionId: void 0,
1459
+ hasError: false,
1460
+ errorMessage: "",
1461
+ userActionRequest: void 0,
1462
+ userActionPending: false,
1463
+ userActionResult: void 0,
1464
+ finalData: void 0,
1465
+ steps: [],
1466
+ stepCounter: 0,
1467
+ currentExecutingStepId: void 0
1468
+ };
1469
+ }
1470
+ function processStreamEventV2(event, state) {
1471
+ const eventType = event.eventType;
1472
+ if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
1473
+ if (event.executionId) state.executionId = event.executionId;
1474
+ if (event.sessionId) state.sessionId = event.sessionId;
1475
+ return state;
1476
+ }
1477
+ if (event.executionId) state.executionId = event.executionId;
1478
+ if (event.sessionId) state.sessionId = event.sessionId;
1479
+ const message = getEventMessage(event);
1480
+ switch (eventType) {
1481
+ case "WORKFLOW_STARTED":
1482
+ case "STARTED":
1483
+ state.lastEventType = eventType;
1484
+ break;
1485
+ case "INTENT_THINKING": {
1486
+ const worker = getEventText(event, "workerName") || "Worker";
1487
+ const msg = getEventText(event, "message") || "Thinking...";
1488
+ const showHeader = shouldShowIntentHeader(event);
1489
+ if (worker !== state.currentWorker) {
1490
+ state.currentWorker = worker;
1491
+ if (showHeader && msg && msg !== worker) {
1492
+ addThinkingLine(state, `**${worker}**`, msg);
1493
+ } else if (showHeader) {
1494
+ addThinkingHeader(state, `**${worker}**`);
1495
+ } else if (msg !== "Thinking...") {
1496
+ addThinkingDetail(state, msg);
1497
+ }
1498
+ } else if ((showHeader || msg !== "Thinking...")) {
1499
+ appendThinkingText(state, "\n" + msg);
1500
+ }
1501
+ const lastInProgress = [...state.steps].reverse().find((s) => s.status === "in_progress");
1502
+ if (lastInProgress) {
1503
+ lastInProgress.thinkingText = "";
1504
+ lastInProgress.isThinking = true;
1505
+ }
1506
+ state.lastEventType = "INTENT_THINKING";
1507
+ break;
1508
+ }
1509
+ case "INTENT_THINKING_CONT": {
1510
+ const msg = event.message || "";
1511
+ if (!msg) break;
1512
+ if (state.lastEventType === "INTENT_THINKING") {
1513
+ appendThinkingText(state, "\n" + msg);
1514
+ } else {
1515
+ appendThinkingText(state, msg);
1516
+ }
1517
+ const thinkingStep = [...state.steps].reverse().find((s) => s.isThinking);
1518
+ if (thinkingStep) {
1519
+ thinkingStep.thinkingText = (thinkingStep.thinkingText || "") + msg;
1520
+ }
1521
+ state.lastEventType = "INTENT_THINKING_CONT";
1522
+ break;
1523
+ }
1524
+ case "ORCHESTRATOR_THINKING": {
1525
+ addThinkingLine(state, "**Planning**", event.message || "Understanding your request...");
1526
+ const stepId = `step-${state.stepCounter++}`;
1527
+ state.steps.push({
1528
+ id: stepId,
1529
+ eventType,
1530
+ message,
1531
+ status: "in_progress",
1532
+ timestamp: Date.now(),
1533
+ elapsedMs: event.elapsedMs
1534
+ });
1535
+ state.currentExecutingStepId = stepId;
1536
+ state.lastEventType = eventType;
1537
+ break;
1538
+ }
1539
+ case "ORCHESTRATOR_COMPLETED": {
1540
+ const workingDetail = workingPhaseDetailForDisplay(message);
1541
+ if (workingDetail) {
1542
+ addThinkingLine(state, "**Working**", workingDetail);
1543
+ } else {
1544
+ addThinkingHeader(state, "**Working**");
1545
+ }
1546
+ state.steps.push({
1547
+ id: `step-${state.stepCounter++}`,
1548
+ eventType: "WORKING",
1549
+ message: workingDetail,
1550
+ status: "completed",
1551
+ timestamp: Date.now()
1552
+ });
1553
+ const step = state.steps.find((s) => s.eventType === "ORCHESTRATOR_THINKING" && s.status === "in_progress");
1554
+ if (step) {
1555
+ step.status = "completed";
1556
+ if (event.elapsedMs) step.elapsedMs = event.elapsedMs;
1557
+ if (step.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
1558
+ }
1559
+ state.lastEventType = eventType;
1560
+ break;
1561
+ }
1562
+ case "INTENT_STARTED": {
1563
+ const worker = getEventText(event, "workerName") || "Worker";
1564
+ const msg = getEventText(event, "message") || "Starting...";
1565
+ const showHeader = shouldShowIntentHeader(event);
1566
+ state.currentWorker = worker;
1567
+ if (showHeader && msg !== worker) {
1568
+ addThinkingLine(state, `**${worker}**`, msg);
1569
+ } else if (showHeader) {
1570
+ addThinkingHeader(state, `**${worker}**`);
1571
+ } else {
1572
+ addThinkingDetail(state, msg);
1573
+ }
1574
+ const thinkingStep = state.steps.find((s) => s.isThinking);
1575
+ if (thinkingStep) thinkingStep.isThinking = false;
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 "INTENT_COMPLETED": {
1590
+ const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
1591
+ if (intentStep) {
1592
+ intentStep.status = "completed";
1593
+ intentStep.isThinking = false;
1594
+ if (event.elapsedMs) intentStep.elapsedMs = event.elapsedMs;
1595
+ if (intentStep.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
1596
+ }
1597
+ state.lastEventType = eventType;
1598
+ break;
1599
+ }
1600
+ case "AGGREGATOR_THINKING": {
1601
+ addThinkingLine(state, "**Finalizing**", event.message || "Preparing response...");
1602
+ const stepId = `step-${state.stepCounter++}`;
1603
+ state.steps.push({
1604
+ id: stepId,
1605
+ eventType,
1606
+ message,
1607
+ status: "in_progress",
1608
+ timestamp: Date.now(),
1609
+ elapsedMs: event.elapsedMs
1610
+ });
1611
+ state.currentExecutingStepId = stepId;
1612
+ state.lastEventType = eventType;
1613
+ break;
1614
+ }
1615
+ case "AGGREGATOR_COMPLETED": {
1616
+ appendThinkingText(state, "\n" + (event.message || "Response ready"));
1617
+ const step = state.steps.find((s) => s.eventType === "AGGREGATOR_THINKING" && s.status === "in_progress");
1618
+ if (step) {
1619
+ step.status = "completed";
1620
+ if (event.elapsedMs) step.elapsedMs = event.elapsedMs;
1621
+ if (step.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
1622
+ }
1623
+ state.lastEventType = eventType;
1624
+ break;
1625
+ }
1626
+ case "WORKFLOW_COMPLETED":
1627
+ case "COMPLETED": {
1628
+ let content = extractResponseContent(event.response);
1629
+ const trace = event.trace && typeof event.trace === "object" ? event.trace : null;
1630
+ if (!content && trace?.workflowMsg && typeof trace.workflowMsg === "string") {
1631
+ content = trace.workflowMsg;
1632
+ }
1633
+ if (!content && trace?.aggregator && typeof trace.aggregator === "object") {
1634
+ const agg = trace.aggregator;
1635
+ if (typeof agg.response === "string") content = agg.response;
1636
+ else content = extractResponseContent(agg.response);
1637
+ }
1638
+ if (content) {
1639
+ state.finalResponse = content;
1640
+ state.finalData = event.response ?? event.trace;
1641
+ state.hasError = false;
1642
+ state.errorMessage = "";
1643
+ } else {
1644
+ state.hasError = true;
1645
+ state.errorMessage = "WORKFLOW_FAILED";
1646
+ }
1647
+ state.steps.forEach((step) => {
1648
+ if (step.status === "in_progress") {
1649
+ step.status = "completed";
1650
+ step.isThinking = false;
1651
+ }
1652
+ });
1653
+ state.lastEventType = eventType;
1654
+ break;
1655
+ }
1656
+ case "USER_ACTION_REQUIRED": {
1657
+ completeLastInProgressStep2(state.steps);
1658
+ if (event.userActionRequest) {
1659
+ state.userActionRequest = {
1660
+ userActionId: event.userActionRequest.userActionId,
1661
+ userActionType: event.userActionRequest.userActionType,
1662
+ message: event.userActionRequest.message,
1663
+ requestedSchema: event.userActionRequest.requestedSchema,
1664
+ metadata: event.userActionRequest.metadata
1665
+ };
1666
+ }
1667
+ state.userActionPending = true;
1668
+ const req = event.userActionRequest;
1669
+ if (req) {
1670
+ addThinkingLine(state, "**Verification Required**", req.message || "Waiting for authorization...");
1671
+ }
1672
+ const stepId = `step-${state.stepCounter++}`;
1673
+ state.steps.push({
1674
+ id: stepId,
1675
+ eventType,
1676
+ message,
1677
+ status: "in_progress",
1678
+ timestamp: Date.now(),
1679
+ elapsedMs: event.elapsedMs
1680
+ });
1681
+ state.currentExecutingStepId = stepId;
1682
+ state.lastEventType = eventType;
1683
+ break;
1684
+ }
1685
+ case "USER_ACTION_SUCCESS": {
1686
+ appendThinkingText(state, "\n\u2713 " + (event.message || "Verification successful"));
1687
+ completeLastInProgressStep2(state.steps);
1688
+ state.userActionRequest = void 0;
1689
+ state.userActionPending = false;
1690
+ state.userActionResult = "approved";
1691
+ const stepId = `step-${state.stepCounter++}`;
1692
+ state.steps.push({
1693
+ id: stepId,
1694
+ eventType,
1695
+ message,
1696
+ status: "completed",
1697
+ timestamp: Date.now(),
1698
+ elapsedMs: event.elapsedMs
1699
+ });
1700
+ state.lastEventType = eventType;
1701
+ break;
1702
+ }
1703
+ case "USER_ACTION_INVALID": {
1704
+ completeLastInProgressStep2(state.steps);
1705
+ const errorStepId = `step-${state.stepCounter++}`;
1706
+ state.steps.push({
1707
+ id: errorStepId,
1708
+ eventType,
1709
+ message,
1710
+ status: "error",
1711
+ timestamp: Date.now(),
1712
+ elapsedMs: event.elapsedMs
1713
+ });
1714
+ const retryStepId = `step-${state.stepCounter++}`;
1715
+ state.steps.push({
1716
+ id: retryStepId,
1717
+ eventType: "USER_ACTION_REQUIRED",
1718
+ message: "Waiting for verification...",
1719
+ status: "in_progress",
1720
+ timestamp: Date.now()
1721
+ });
1722
+ state.currentExecutingStepId = retryStepId;
1723
+ state.lastEventType = eventType;
1724
+ break;
1725
+ }
1726
+ case "USER_ACTION_REJECTED": {
1727
+ appendThinkingText(state, "\n\u2717 " + (event.message || "Verification rejected"));
1728
+ completeLastInProgressStep2(state.steps);
1729
+ state.userActionRequest = void 0;
1730
+ state.userActionPending = false;
1731
+ state.userActionResult = "rejected";
1732
+ const stepId = `step-${state.stepCounter++}`;
1733
+ state.steps.push({
1734
+ id: stepId,
1735
+ eventType,
1736
+ message,
1737
+ status: "completed",
1738
+ timestamp: Date.now(),
1739
+ elapsedMs: event.elapsedMs
1740
+ });
1741
+ state.lastEventType = eventType;
1742
+ break;
1743
+ }
1744
+ case "USER_ACTION_EXPIRED": {
1745
+ appendThinkingText(state, "\n\u2717 " + (event.message || "Verification expired"));
1746
+ completeLastInProgressStep2(state.steps);
1747
+ state.userActionRequest = void 0;
1748
+ state.userActionPending = false;
1749
+ const stepId = `step-${state.stepCounter++}`;
1750
+ state.steps.push({
1751
+ id: stepId,
1752
+ eventType,
1753
+ message,
1754
+ status: "error",
1755
+ timestamp: Date.now(),
1756
+ elapsedMs: event.elapsedMs
1757
+ });
1758
+ state.lastEventType = eventType;
1759
+ break;
1760
+ }
1761
+ case "USER_ACTION_RESENT": {
1762
+ const stepId = `step-${state.stepCounter++}`;
1763
+ state.steps.push({
1764
+ id: stepId,
1765
+ eventType,
1766
+ message,
1767
+ status: "completed",
1768
+ timestamp: Date.now(),
1769
+ elapsedMs: event.elapsedMs
1770
+ });
1771
+ state.lastEventType = eventType;
1772
+ break;
1773
+ }
1774
+ case "USER_ACTION_FAILED": {
1775
+ appendThinkingText(state, "\n\u2717 " + (event.message || "Verification failed"));
1776
+ completeLastInProgressStep2(state.steps);
1777
+ state.userActionRequest = void 0;
1778
+ state.userActionPending = false;
1779
+ const stepId = `step-${state.stepCounter++}`;
1780
+ state.steps.push({
1781
+ id: stepId,
1782
+ eventType,
1783
+ message,
1784
+ status: "error",
1785
+ timestamp: Date.now(),
1786
+ elapsedMs: event.elapsedMs
1787
+ });
1788
+ state.lastEventType = eventType;
1789
+ break;
1790
+ }
1791
+ case "WORKFLOW_ERROR":
1792
+ case "ERROR":
1793
+ state.hasError = true;
1794
+ state.errorMessage = event.errorMessage || event.message || "Workflow error";
1795
+ state.lastEventType = eventType;
1796
+ break;
1797
+ case "INTENT_ERROR": {
1798
+ state.errorMessage = message || event.errorMessage || "An error occurred";
1799
+ const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
1800
+ if (intentStep) {
1801
+ intentStep.status = "error";
1802
+ intentStep.isThinking = false;
1803
+ }
1804
+ state.lastEventType = eventType;
1805
+ break;
1806
+ }
1807
+ default:
1808
+ state.lastEventType = eventType;
1809
+ break;
1810
+ }
1811
+ return state;
1812
+ }
1813
+
1814
+ // src/hooks/useStreamManagerV2.ts
1815
+ var FRIENDLY_ERROR_MESSAGE2 = "Oops, something went wrong. Please try again.";
1816
+ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForResponse) {
1817
+ const abortControllerRef = react.useRef(null);
1818
+ const configRef = react.useRef(config);
1819
+ configRef.current = config;
1820
+ const callbacksRef = react.useRef(callbacks);
1821
+ callbacksRef.current = callbacks;
1822
+ const startStream = react.useCallback(
1823
+ async (userMessage, streamingId, sessionId, externalAbortController) => {
1824
+ abortControllerRef.current?.abort();
1825
+ const abortController = externalAbortController ?? new AbortController();
1826
+ abortControllerRef.current = abortController;
1827
+ const state = createInitialV2State();
1828
+ const updateMessage = (update) => {
1829
+ if (abortController.signal.aborted) return;
1830
+ setMessages(
1831
+ (prev) => prev.map(
1832
+ (msg) => msg.id === streamingId ? { ...msg, ...update } : msg
1833
+ )
1834
+ );
1835
+ };
1836
+ const currentConfig = configRef.current;
1837
+ const requestBody = buildRequestBody(currentConfig, userMessage, sessionId);
1838
+ const url = buildStreamingUrl(currentConfig);
1839
+ const headers = buildRequestHeaders(currentConfig);
1840
+ try {
1841
+ await streamWorkflowEvents(url, requestBody, headers, {
1842
+ signal: abortController.signal,
1843
+ onEvent: (event) => {
1844
+ if (abortController.signal.aborted) return;
1845
+ if (typeof event.eventType === "string" && event.eventType.toUpperCase() === "KEEP_ALIVE") {
1846
+ if (event.executionId) state.executionId = event.executionId;
1847
+ if (event.sessionId) state.sessionId = event.sessionId;
1848
+ return;
1849
+ }
1850
+ processStreamEventV2(event, state);
1851
+ const eventType = event.eventType;
1852
+ if (eventType === "USER_ACTION_REQUIRED" && state.userActionRequest) {
1853
+ callbacksRef.current.onUserActionRequired?.(state.userActionRequest);
1854
+ } else if (eventType.startsWith("USER_ACTION_") && eventType !== "USER_ACTION_REQUIRED") {
1855
+ const msg = event.message?.trim() || event.errorMessage?.trim() || getEventMessage(event);
1856
+ callbacksRef.current.onUserActionEvent?.(eventType, msg);
1857
+ }
1858
+ const activeStep = state.steps.find((s) => s.id === state.currentExecutingStepId);
1859
+ const lastInProgressStep = [...state.steps].reverse().find((s) => s.status === "in_progress");
1860
+ const currentMessage = activeStep?.message || lastInProgressStep?.message || getEventMessage(event);
1861
+ if (state.hasError) {
1862
+ updateMessage({
1863
+ streamingContent: FRIENDLY_ERROR_MESSAGE2,
1864
+ content: FRIENDLY_ERROR_MESSAGE2,
1865
+ streamProgress: "error",
1866
+ isError: true,
1867
+ errorDetails: state.errorMessage,
1868
+ formattedThinkingText: state.formattedThinkingText || void 0,
1869
+ steps: [...state.steps],
1870
+ currentExecutingStepId: void 0,
1871
+ executionId: state.executionId,
1872
+ sessionId: state.sessionId
1873
+ });
1874
+ } else {
1875
+ updateMessage({
1876
+ streamingContent: "",
1877
+ content: "",
1878
+ currentMessage,
1879
+ streamProgress: "processing",
1880
+ isError: false,
1881
+ formattedThinkingText: state.formattedThinkingText || void 0,
1882
+ steps: [...state.steps],
1883
+ currentExecutingStepId: state.currentExecutingStepId,
1884
+ executionId: state.executionId,
1885
+ sessionId: state.sessionId,
1886
+ userActionResult: state.userActionResult,
1887
+ isCancelled: false
1888
+ });
1889
+ }
1890
+ },
1891
+ onError: (error) => {
1892
+ setIsWaitingForResponse(false);
1893
+ if (error.name !== "AbortError") {
1894
+ callbacksRef.current.onError?.(error);
1895
+ }
1896
+ if (state.userActionPending) {
1897
+ state.userActionPending = false;
1898
+ state.userActionRequest = void 0;
1899
+ callbacksRef.current.onUserActionEvent?.(
1900
+ "USER_ACTION_FAILED",
1901
+ "Connection lost. Please try again."
1902
+ );
1903
+ }
1904
+ const isAborted = error.name === "AbortError";
1905
+ setMessages(
1906
+ (prev) => prev.map(
1907
+ (msg) => msg.id === streamingId ? {
1908
+ ...msg,
1909
+ isStreaming: false,
1910
+ streamProgress: isAborted ? "processing" : "error",
1911
+ isError: !isAborted,
1912
+ isCancelled: isAborted,
1913
+ errorDetails: isAborted ? void 0 : error.message,
1914
+ content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE2,
1915
+ currentMessage: isAborted ? "Thinking..." : void 0,
1916
+ formattedThinkingText: state.formattedThinkingText || void 0,
1917
+ steps: [...state.steps].map((step) => {
1918
+ if (step.status === "in_progress" && isAborted) {
1919
+ return { ...step, status: "pending" };
1920
+ }
1921
+ return step;
1922
+ }),
1923
+ currentExecutingStepId: void 0
1924
+ } : msg
1925
+ )
1926
+ );
1927
+ },
1928
+ onComplete: () => {
1929
+ setIsWaitingForResponse(false);
1930
+ if (state.userActionPending) {
1931
+ state.userActionPending = false;
1932
+ state.userActionRequest = void 0;
1933
+ callbacksRef.current.onUserActionEvent?.(
1934
+ "USER_ACTION_FAILED",
1935
+ "Verification could not be completed."
1936
+ );
1937
+ }
1938
+ if (state.sessionId && state.sessionId !== sessionId) {
1939
+ callbacksRef.current.onSessionIdChange?.(state.sessionId);
1940
+ }
1941
+ const needsImageResolve = !state.hasError && !abortController.signal.aborted && hasRagImages(state.finalResponse);
1942
+ const finalMessage = {
1943
+ id: streamingId,
1944
+ sessionId: state.sessionId || sessionId,
1945
+ role: "assistant",
1946
+ content: state.hasError ? FRIENDLY_ERROR_MESSAGE2 : state.finalResponse || "",
1947
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1948
+ isStreaming: false,
1949
+ streamProgress: state.hasError ? "error" : "completed",
1950
+ isError: state.hasError,
1951
+ errorDetails: state.hasError ? state.errorMessage : void 0,
1952
+ executionId: state.executionId,
1953
+ tracingData: state.finalData,
1954
+ steps: state.hasError ? [] : [...state.steps],
1955
+ isCancelled: false,
1956
+ currentExecutingStepId: void 0,
1957
+ userActionResult: state.userActionResult,
1958
+ formattedThinkingText: state.hasError ? void 0 : state.formattedThinkingText || void 0,
1959
+ isResolvingImages: needsImageResolve
1960
+ };
1961
+ setMessages(
1962
+ (prev) => prev.map(
1963
+ (msg) => msg.id === streamingId ? finalMessage : msg
1964
+ )
1965
+ );
1966
+ callbacksRef.current.onStreamComplete?.(finalMessage);
1967
+ }
1968
+ });
1969
+ const shouldResolveImages = !abortController.signal.aborted && !state.hasError && hasRagImages(state.finalResponse);
1970
+ if (shouldResolveImages) {
1971
+ await waitForNextPaint(abortController.signal);
1972
+ }
1973
+ if (shouldResolveImages && !abortController.signal.aborted) {
1974
+ try {
1975
+ const resolvedContent = await resolveRagImageUrls(
1976
+ currentConfig,
1977
+ state.finalResponse,
1978
+ abortController.signal
1979
+ );
1980
+ setMessages(
1981
+ (prev) => prev.map(
1982
+ (msg) => msg.id === streamingId ? { ...msg, content: resolvedContent, isResolvingImages: false } : msg
1983
+ )
1984
+ );
1985
+ } catch {
1986
+ setMessages(
1987
+ (prev) => prev.map(
1988
+ (msg) => msg.id === streamingId ? { ...msg, isResolvingImages: false } : msg
1989
+ )
1990
+ );
1991
+ }
1992
+ }
1993
+ return state.sessionId;
1994
+ } catch (error) {
1995
+ setIsWaitingForResponse(false);
1996
+ if (error.name !== "AbortError") {
1997
+ callbacksRef.current.onError?.(error);
1998
+ }
1999
+ if (state.userActionPending) {
2000
+ state.userActionPending = false;
2001
+ state.userActionRequest = void 0;
2002
+ callbacksRef.current.onUserActionEvent?.(
2003
+ "USER_ACTION_FAILED",
2004
+ "Connection lost. Please try again."
2005
+ );
2006
+ }
2007
+ const isAborted = error.name === "AbortError";
2008
+ setMessages(
2009
+ (prev) => prev.map(
2010
+ (msg) => msg.id === streamingId ? {
2011
+ ...msg,
2012
+ isStreaming: false,
2013
+ streamProgress: isAborted ? "processing" : "error",
2014
+ isError: !isAborted,
2015
+ isCancelled: isAborted,
2016
+ errorDetails: isAborted ? void 0 : error.message,
2017
+ content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE2,
2018
+ formattedThinkingText: state.formattedThinkingText || void 0,
2019
+ steps: [...state.steps].map((step) => {
2020
+ if (step.status === "in_progress" && isAborted) {
2021
+ return { ...step, status: "pending" };
2022
+ }
2023
+ return step;
2024
+ }),
2025
+ currentExecutingStepId: void 0
2026
+ } : msg
2027
+ )
2028
+ );
2029
+ return state.sessionId;
2030
+ }
2031
+ },
2032
+ [setMessages, setIsWaitingForResponse]
2033
+ );
2034
+ const cancelStream = react.useCallback(() => {
2035
+ abortControllerRef.current?.abort();
2036
+ }, []);
2037
+ return {
2038
+ startStream,
2039
+ cancelStream,
2040
+ abortControllerRef
2041
+ };
2042
+ }
2043
+
2044
+ // src/hooks/useChatV2.ts
2045
+ function useChatV2(config, callbacks = {}) {
2046
+ const [messages, setMessages] = react.useState(() => {
2047
+ if (config.userId) return chatStore.get(config.userId);
2048
+ return config.initialMessages ?? [];
2049
+ });
2050
+ const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(false);
2051
+ const sessionIdRef = react.useRef(
2052
+ config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
2053
+ );
2054
+ const prevUserIdRef = react.useRef(config.userId);
2055
+ const callbacksRef = react.useRef(callbacks);
2056
+ callbacksRef.current = callbacks;
2057
+ const configRef = react.useRef(config);
2058
+ configRef.current = config;
2059
+ const messagesRef = react.useRef(messages);
2060
+ messagesRef.current = messages;
2061
+ const storeAwareSetMessages = react.useCallback(
2062
+ (updater) => {
2063
+ const { userId } = configRef.current;
2064
+ if (userId && activeStreamStore.has(userId)) {
2065
+ activeStreamStore.applyMessages(userId, updater);
2066
+ }
2067
+ setMessages(updater);
2068
+ },
2069
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2070
+ []
2071
+ );
2072
+ const storeAwareSetIsWaiting = react.useCallback(
2073
+ (waiting) => {
2074
+ const { userId } = configRef.current;
2075
+ if (userId && activeStreamStore.has(userId)) {
2076
+ activeStreamStore.setWaiting(userId, waiting);
2077
+ }
2078
+ setIsWaitingForResponse(waiting);
2079
+ },
2080
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2081
+ []
2082
+ );
2083
+ const [userActionState, setUserActionState] = react.useState({
2084
+ request: null,
2085
+ result: null,
2086
+ clearOtpTrigger: 0
2087
+ });
2088
+ const userActionStateRef = react.useRef(userActionState);
2089
+ userActionStateRef.current = userActionState;
2090
+ const wrappedCallbacks = react.useMemo(() => ({
2091
+ ...callbacksRef.current,
2092
+ onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
2093
+ onStreamStart: () => callbacksRef.current.onStreamStart?.(),
2094
+ onStreamComplete: (message) => callbacksRef.current.onStreamComplete?.(message),
2095
+ onError: (error) => callbacksRef.current.onError?.(error),
2096
+ onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
2097
+ onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
2098
+ onUserActionRequired: (request) => {
2099
+ setUserActionState((prev) => ({ ...prev, request, result: null }));
2100
+ callbacksRef.current.onUserActionRequired?.(request);
2101
+ },
2102
+ onUserActionEvent: (eventType, message) => {
2103
+ switch (eventType) {
2104
+ case "USER_ACTION_SUCCESS":
2105
+ setUserActionState((prev) => ({ ...prev, request: null, result: "approved" }));
2106
+ break;
2107
+ case "USER_ACTION_REJECTED":
2108
+ setUserActionState((prev) => ({ ...prev, request: null, result: "rejected" }));
2109
+ break;
2110
+ case "USER_ACTION_EXPIRED":
2111
+ case "USER_ACTION_FAILED":
2112
+ setUserActionState((prev) => ({ ...prev, request: null }));
2113
+ break;
2114
+ case "USER_ACTION_INVALID":
2115
+ setUserActionState((prev) => ({ ...prev, clearOtpTrigger: prev.clearOtpTrigger + 1 }));
2116
+ break;
2117
+ }
2118
+ callbacksRef.current.onUserActionEvent?.(eventType, message);
2119
+ }
2120
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2121
+ }), []);
2122
+ const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManagerV2(
2123
+ config,
2124
+ wrappedCallbacks,
2125
+ storeAwareSetMessages,
2126
+ storeAwareSetIsWaiting
2127
+ );
2128
+ const sendMessage = react.useCallback(
2129
+ async (userMessage) => {
2130
+ if (!userMessage.trim()) return;
2131
+ if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
2132
+ sessionIdRef.current = generateId();
2133
+ callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
2134
+ }
2135
+ const userMessageId = `user-${Date.now()}`;
2136
+ const userMsg = {
2137
+ id: userMessageId,
2138
+ sessionId: sessionIdRef.current,
2139
+ role: "user",
2140
+ content: userMessage,
2141
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2142
+ };
2143
+ setMessages((prev) => [...prev, userMsg]);
2144
+ callbacksRef.current.onMessageSent?.(userMessage);
2145
+ setIsWaitingForResponse(true);
2146
+ callbacksRef.current.onStreamStart?.();
2147
+ const streamingId = `assistant-${Date.now()}`;
2148
+ const streamingMsg = {
2149
+ id: streamingId,
2150
+ sessionId: sessionIdRef.current,
2151
+ role: "assistant",
2152
+ content: "",
2153
+ streamingContent: "",
2154
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2155
+ isStreaming: true,
2156
+ streamProgress: "started",
2157
+ steps: [],
2158
+ currentExecutingStepId: void 0,
2159
+ isCancelled: false,
2160
+ currentMessage: void 0
2161
+ };
2162
+ setMessages((prev) => [...prev, streamingMsg]);
2163
+ const abortController = new AbortController();
2164
+ const { userId } = configRef.current;
2165
+ if (userId) {
2166
+ const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
2167
+ activeStreamStore.start(userId, abortController, initialMessages);
2168
+ }
2169
+ const newSessionId = await startStream(
2170
+ userMessage,
2171
+ streamingId,
2172
+ sessionIdRef.current,
2173
+ abortController
2174
+ );
2175
+ if (userId) {
2176
+ activeStreamStore.complete(userId);
2177
+ }
2178
+ if (!abortController.signal.aborted && newSessionId && newSessionId !== sessionIdRef.current) {
2179
+ sessionIdRef.current = newSessionId;
2180
+ }
2181
+ },
2182
+ [startStream]
2183
+ );
2184
+ const clearMessages = react.useCallback(() => {
2185
+ if (configRef.current.userId) {
2186
+ chatStore.delete(configRef.current.userId);
2187
+ }
2188
+ setMessages([]);
2189
+ }, []);
2190
+ const prependMessages = react.useCallback((msgs) => {
2191
+ setMessages((prev) => [...msgs, ...prev]);
2192
+ }, []);
2193
+ const cancelStream = react.useCallback(() => {
2194
+ if (configRef.current.userId) {
2195
+ activeStreamStore.abort(configRef.current.userId);
2196
+ }
2197
+ cancelStreamManager();
2198
+ setIsWaitingForResponse(false);
2199
+ setUserActionState((prev) => ({ ...prev, request: null, result: null }));
2200
+ setMessages(
2201
+ (prev) => prev.map((msg) => {
2202
+ if (msg.isStreaming) {
2203
+ return {
2204
+ ...msg,
2205
+ ...createCancelledMessageUpdate(
2206
+ msg.steps || [],
2207
+ msg.currentMessage
2208
+ )
2209
+ };
2210
+ }
2211
+ return msg;
2212
+ })
2213
+ );
2214
+ }, [cancelStreamManager]);
2215
+ const resetSession = react.useCallback(() => {
2216
+ if (configRef.current.userId) {
2217
+ activeStreamStore.abort(configRef.current.userId);
2218
+ chatStore.delete(configRef.current.userId);
2219
+ }
2220
+ setMessages([]);
2221
+ sessionIdRef.current = void 0;
2222
+ abortControllerRef.current?.abort();
2223
+ setIsWaitingForResponse(false);
2224
+ setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
2225
+ }, []);
2226
+ const getSessionId = react.useCallback(() => {
2227
+ return sessionIdRef.current;
2228
+ }, []);
2229
+ const getMessages = react.useCallback(() => {
2230
+ return messages;
2231
+ }, [messages]);
2232
+ const approveUserAction = react.useCallback(
2233
+ async (otp) => {
2234
+ const request = userActionStateRef.current.request;
2235
+ if (!request) return;
2236
+ try {
2237
+ await submitUserAction(configRef.current, request.userActionId, { otp });
2238
+ } catch (error) {
2239
+ setUserActionState((prev) => ({
2240
+ ...prev,
2241
+ clearOtpTrigger: prev.clearOtpTrigger + 1
2242
+ }));
2243
+ callbacksRef.current.onError?.(error);
2244
+ throw error;
2245
+ }
2246
+ },
2247
+ []
2248
+ );
2249
+ const rejectUserAction = react.useCallback(async () => {
2250
+ const request = userActionStateRef.current.request;
2251
+ if (!request) return;
2252
+ try {
2253
+ setMessages((prev) => {
2254
+ let lastStreamingIdx = -1;
2255
+ for (let i = prev.length - 1; i >= 0; i--) {
2256
+ if (prev[i].role === "assistant" && prev[i].isStreaming) {
2257
+ lastStreamingIdx = i;
2258
+ break;
2259
+ }
2260
+ }
2261
+ if (lastStreamingIdx === -1) return prev;
2262
+ return prev.map(
2263
+ (msg, i) => i === lastStreamingIdx ? { ...msg, currentMessage: "Rejecting..." } : msg
2264
+ );
2265
+ });
2266
+ await cancelUserAction(configRef.current, request.userActionId);
2267
+ } catch (error) {
2268
+ callbacksRef.current.onError?.(error);
2269
+ throw error;
2270
+ }
2271
+ }, []);
2272
+ const resendOtp = react.useCallback(async () => {
2273
+ const request = userActionStateRef.current.request;
2274
+ if (!request) return;
2275
+ try {
2276
+ await resendUserAction(configRef.current, request.userActionId);
2277
+ } catch (error) {
2278
+ callbacksRef.current.onError?.(error);
2279
+ throw error;
2280
+ }
2281
+ }, []);
2282
+ react.useEffect(() => {
2283
+ const { userId } = config;
2284
+ if (!userId) return;
2285
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
2286
+ setMessages(msgs);
2287
+ setIsWaitingForResponse(isWaiting);
2288
+ });
2289
+ const active = activeStreamStore.get(userId);
2290
+ if (active) {
2291
+ setMessages(active.messages);
2292
+ setIsWaitingForResponse(active.isWaiting);
2293
+ }
2294
+ return unsubscribe;
2295
+ }, []);
2296
+ react.useEffect(() => {
2297
+ if (!config.userId) return;
2298
+ const toSave = messages.filter((m) => !m.isStreaming);
2299
+ if (toSave.length > 0) {
2300
+ chatStore.set(config.userId, toSave);
2301
+ }
2302
+ }, [messages, config.userId]);
2303
+ react.useEffect(() => {
2304
+ const prevUserId = prevUserIdRef.current;
2305
+ prevUserIdRef.current = config.userId;
2306
+ if (prevUserId === config.userId) return;
2307
+ if (prevUserId && !config.userId) {
2308
+ chatStore.delete(prevUserId);
2309
+ setMessages([]);
2310
+ sessionIdRef.current = void 0;
2311
+ setIsWaitingForResponse(false);
2312
+ setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
2313
+ } else if (config.userId) {
2314
+ const stored = chatStore.get(config.userId);
2315
+ setMessages(stored);
2316
+ sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
2317
+ }
2318
+ }, [config.userId]);
2319
+ return {
2320
+ messages,
2321
+ sendMessage,
2322
+ clearMessages,
2323
+ prependMessages,
2324
+ cancelStream,
2325
+ resetSession,
2326
+ getSessionId,
2327
+ getMessages,
2328
+ isWaitingForResponse,
2329
+ sessionId: sessionIdRef.current,
2330
+ userActionState,
2331
+ approveUserAction,
2332
+ rejectUserAction,
2333
+ resendOtp
2334
+ };
2335
+ }
1330
2336
  function useVoice() {
1331
2337
  const [voiceState, setVoiceState] = react.useState("idle");
1332
2338
  const [transcribedText, setTranscribedText] = react.useState("");
@@ -1443,12 +2449,17 @@ function useVoice() {
1443
2449
  };
1444
2450
  }
1445
2451
 
2452
+ exports.buildFormattedThinking = buildFormattedThinking;
1446
2453
  exports.cancelUserAction = cancelUserAction;
2454
+ exports.createInitialV2State = createInitialV2State;
1447
2455
  exports.generateId = generateId;
2456
+ exports.processStreamEventV2 = processStreamEventV2;
1448
2457
  exports.resendUserAction = resendUserAction;
1449
2458
  exports.streamWorkflowEvents = streamWorkflowEvents;
1450
2459
  exports.submitUserAction = submitUserAction;
1451
2460
  exports.useChat = useChat;
2461
+ exports.useChatV2 = useChatV2;
1452
2462
  exports.useVoice = useVoice;
2463
+ exports.workingPhaseDetailForDisplay = workingPhaseDetailForDisplay;
1453
2464
  //# sourceMappingURL=index.native.js.map
1454
2465
  //# sourceMappingURL=index.native.js.map