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