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