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