@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.d.mts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +1015 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1011 -5
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +1015 -4
- package/dist/index.native.js.map +1 -1
- package/package.json +1 -1
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
|
|
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:
|
|
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
|
|
616
|
+
steps,
|
|
530
617
|
isCancelled: false,
|
|
531
618
|
currentExecutingStepId: void 0,
|
|
532
619
|
userActionResult: state.userActionResult,
|
|
533
620
|
activeThinkingText: void 0,
|
|
534
|
-
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
|