@paymanai/payman-typescript-ask-sdk 4.0.8 → 4.0.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 +202 -29
- package/dist/index.d.ts +202 -29
- package/dist/index.js +392 -292
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +380 -293
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +392 -292
- package/dist/index.native.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
6
8
|
|
|
7
9
|
// src/utils/generateId.ts
|
|
8
10
|
function generateId() {
|
|
@@ -258,31 +260,27 @@ function normalizeEvent(event) {
|
|
|
258
260
|
return event;
|
|
259
261
|
}
|
|
260
262
|
}
|
|
261
|
-
function
|
|
262
|
-
|
|
263
|
+
function isVerificationSchema(schema) {
|
|
264
|
+
const props = schema?.properties;
|
|
265
|
+
if (!props) return false;
|
|
266
|
+
const keys = Object.keys(props);
|
|
267
|
+
return keys.length === 1 && keys[0] === "verificationCode";
|
|
263
268
|
}
|
|
264
|
-
function
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
case "
|
|
269
|
-
return
|
|
270
|
-
case "
|
|
271
|
-
return
|
|
272
|
-
case "USER_ACTION_INVALID":
|
|
273
|
-
return safeRaw || "Invalid code. Please try again.";
|
|
274
|
-
case "USER_ACTION_REJECTED":
|
|
275
|
-
return safeRaw || "Verification cancelled";
|
|
276
|
-
case "USER_ACTION_EXPIRED":
|
|
277
|
-
return safeRaw || "Verification expired";
|
|
278
|
-
case "USER_ACTION_RESENT":
|
|
279
|
-
return safeRaw || "Verification code resent";
|
|
280
|
-
case "USER_ACTION_FAILED":
|
|
281
|
-
return safeRaw || "Verification failed";
|
|
269
|
+
function classifyUserActionKind(action, schema) {
|
|
270
|
+
switch ((action || "").toLowerCase()) {
|
|
271
|
+
case "userverificationrequest":
|
|
272
|
+
return "verification";
|
|
273
|
+
case "usernotificationrequest":
|
|
274
|
+
return "notification";
|
|
275
|
+
case "userformrequest":
|
|
276
|
+
return isVerificationSchema(schema) ? "verification" : "form";
|
|
282
277
|
default:
|
|
283
|
-
return
|
|
278
|
+
return isVerificationSchema(schema) ? "verification" : "form";
|
|
284
279
|
}
|
|
285
280
|
}
|
|
281
|
+
function userActionHeader(kind) {
|
|
282
|
+
return kind === "verification" ? "**Verification required**" : "**Action required**";
|
|
283
|
+
}
|
|
286
284
|
function workingPhaseDetailForDisplay(raw) {
|
|
287
285
|
const t = raw.trim();
|
|
288
286
|
if (!t) return "";
|
|
@@ -342,18 +340,32 @@ function createInitialV2State() {
|
|
|
342
340
|
executionId: void 0,
|
|
343
341
|
hasError: false,
|
|
344
342
|
errorMessage: "",
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
343
|
+
userActions: [],
|
|
344
|
+
notifications: [],
|
|
345
|
+
lastUserAction: void 0,
|
|
346
|
+
lastNotification: void 0,
|
|
348
347
|
finalData: void 0,
|
|
349
348
|
steps: [],
|
|
350
349
|
stepCounter: 0,
|
|
351
350
|
currentExecutingStepId: void 0
|
|
352
351
|
};
|
|
353
352
|
}
|
|
353
|
+
function upsertUserAction(state, req) {
|
|
354
|
+
const active = { ...req, status: "pending" };
|
|
355
|
+
const matchIdx = state.userActions.findIndex(
|
|
356
|
+
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
357
|
+
);
|
|
358
|
+
if (matchIdx >= 0) {
|
|
359
|
+
state.userActions[matchIdx] = active;
|
|
360
|
+
} else {
|
|
361
|
+
state.userActions.push(active);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
354
364
|
function processStreamEventV2(rawEvent, state) {
|
|
355
365
|
const event = normalizeEvent(rawEvent);
|
|
356
366
|
const eventType = event.eventType;
|
|
367
|
+
state.lastUserAction = void 0;
|
|
368
|
+
state.lastNotification = void 0;
|
|
357
369
|
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
358
370
|
if (event.executionId) state.executionId = event.executionId;
|
|
359
371
|
if (event.sessionId) state.sessionId = event.sessionId;
|
|
@@ -575,152 +587,72 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
575
587
|
break;
|
|
576
588
|
}
|
|
577
589
|
case "USER_ACTION_REQUIRED": {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
590
|
+
const rawAction = typeof event.action === "string" ? event.action : void 0;
|
|
591
|
+
const schema = event.requestedSchema;
|
|
592
|
+
const kind = classifyUserActionKind(rawAction, schema);
|
|
593
|
+
const promptMessage = typeof event.message === "string" && event.message.trim() || message || "";
|
|
594
|
+
const userActionId = typeof event.userActionId === "string" ? event.userActionId : "";
|
|
595
|
+
if (kind === "notification") {
|
|
596
|
+
const notification = {
|
|
597
|
+
id: userActionId || `note-${state.stepCounter++}`,
|
|
598
|
+
message: promptMessage
|
|
586
599
|
};
|
|
600
|
+
state.notifications.push(notification);
|
|
601
|
+
state.lastNotification = notification;
|
|
602
|
+
if (promptMessage) addThinkingDetail(state, promptMessage);
|
|
603
|
+
state.lastEventType = eventType;
|
|
604
|
+
break;
|
|
587
605
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
eventType,
|
|
592
|
-
req?.message || message
|
|
593
|
-
);
|
|
594
|
-
if (req) {
|
|
595
|
-
addThinkingLine(state, "**Verification Required**", displayMessage);
|
|
606
|
+
if (!userActionId) {
|
|
607
|
+
state.lastEventType = eventType;
|
|
608
|
+
break;
|
|
596
609
|
}
|
|
597
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
598
|
-
state.steps.push({
|
|
599
|
-
id: stepId,
|
|
600
|
-
eventType,
|
|
601
|
-
message: displayMessage,
|
|
602
|
-
status: "in_progress",
|
|
603
|
-
timestamp: Date.now(),
|
|
604
|
-
elapsedMs: event.elapsedMs
|
|
605
|
-
});
|
|
606
|
-
state.currentExecutingStepId = stepId;
|
|
607
|
-
state.lastEventType = eventType;
|
|
608
|
-
break;
|
|
609
|
-
}
|
|
610
|
-
case "USER_ACTION_SUCCESS": {
|
|
611
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
612
|
-
appendThinkingText(state, "\n\u2713 " + displayMessage);
|
|
613
610
|
completeLastInProgressStep(state.steps);
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
611
|
+
const verificationType = event.verificationType === "ALPHANUMERIC_CODE" || event.verificationType === "NUMERIC_CODE" ? event.verificationType : void 0;
|
|
612
|
+
const request = {
|
|
613
|
+
userActionId,
|
|
614
|
+
kind,
|
|
615
|
+
rawAction,
|
|
616
|
+
subAction: typeof event.subAction === "string" ? event.subAction : void 0,
|
|
617
|
+
verificationType,
|
|
618
|
+
expirySeconds: typeof event.expirySeconds === "number" ? event.expirySeconds : void 0,
|
|
619
|
+
message: promptMessage || void 0,
|
|
620
|
+
requestedSchema: schema,
|
|
621
|
+
metadata: event.metadata,
|
|
622
|
+
toolCallId: typeof event.toolCallId === "string" ? event.toolCallId : void 0,
|
|
623
|
+
executionId: state.executionId,
|
|
624
|
+
sessionId: state.sessionId
|
|
625
|
+
};
|
|
626
|
+
upsertUserAction(state, request);
|
|
627
|
+
state.lastUserAction = request;
|
|
628
|
+
const header = userActionHeader(kind);
|
|
629
|
+
if (promptMessage) addThinkingLine(state, header, promptMessage);
|
|
630
|
+
else addThinkingHeader(state, header);
|
|
617
631
|
const stepId = `step-${state.stepCounter++}`;
|
|
618
632
|
state.steps.push({
|
|
619
633
|
id: stepId,
|
|
620
634
|
eventType,
|
|
621
|
-
message:
|
|
622
|
-
status: "completed",
|
|
623
|
-
timestamp: Date.now(),
|
|
624
|
-
elapsedMs: event.elapsedMs
|
|
625
|
-
});
|
|
626
|
-
state.lastEventType = eventType;
|
|
627
|
-
break;
|
|
628
|
-
}
|
|
629
|
-
case "USER_ACTION_INVALID": {
|
|
630
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
631
|
-
appendThinkingText(state, "\n\u2717 " + displayMessage);
|
|
632
|
-
completeLastInProgressStep(state.steps);
|
|
633
|
-
const errorStepId = `step-${state.stepCounter++}`;
|
|
634
|
-
state.steps.push({
|
|
635
|
-
id: errorStepId,
|
|
636
|
-
eventType,
|
|
637
|
-
message: displayMessage,
|
|
638
|
-
status: "error",
|
|
639
|
-
timestamp: Date.now(),
|
|
640
|
-
elapsedMs: event.elapsedMs
|
|
641
|
-
});
|
|
642
|
-
const retryStepId = `step-${state.stepCounter++}`;
|
|
643
|
-
state.steps.push({
|
|
644
|
-
id: retryStepId,
|
|
645
|
-
eventType: "USER_ACTION_REQUIRED",
|
|
646
|
-
message: "Waiting for verification...",
|
|
635
|
+
message: promptMessage || (kind === "verification" ? "Waiting for verification..." : "Waiting for your input..."),
|
|
647
636
|
status: "in_progress",
|
|
648
|
-
timestamp: Date.now()
|
|
649
|
-
});
|
|
650
|
-
state.currentExecutingStepId = retryStepId;
|
|
651
|
-
state.lastEventType = eventType;
|
|
652
|
-
break;
|
|
653
|
-
}
|
|
654
|
-
case "USER_ACTION_REJECTED": {
|
|
655
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
656
|
-
appendThinkingText(state, "\n" + displayMessage);
|
|
657
|
-
completeLastInProgressStep(state.steps);
|
|
658
|
-
state.userActionRequest = void 0;
|
|
659
|
-
state.userActionPending = false;
|
|
660
|
-
state.userActionResult = "rejected";
|
|
661
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
662
|
-
state.steps.push({
|
|
663
|
-
id: stepId,
|
|
664
|
-
eventType,
|
|
665
|
-
message: displayMessage,
|
|
666
|
-
status: "completed",
|
|
667
|
-
timestamp: Date.now(),
|
|
668
|
-
elapsedMs: event.elapsedMs
|
|
669
|
-
});
|
|
670
|
-
state.lastEventType = eventType;
|
|
671
|
-
break;
|
|
672
|
-
}
|
|
673
|
-
case "USER_ACTION_EXPIRED": {
|
|
674
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
675
|
-
appendThinkingText(state, "\n\u2717 " + displayMessage);
|
|
676
|
-
completeLastInProgressStep(state.steps);
|
|
677
|
-
state.userActionRequest = void 0;
|
|
678
|
-
state.userActionPending = false;
|
|
679
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
680
|
-
state.steps.push({
|
|
681
|
-
id: stepId,
|
|
682
|
-
eventType,
|
|
683
|
-
message: displayMessage,
|
|
684
|
-
status: "error",
|
|
685
|
-
timestamp: Date.now(),
|
|
686
|
-
elapsedMs: event.elapsedMs
|
|
687
|
-
});
|
|
688
|
-
state.lastEventType = eventType;
|
|
689
|
-
break;
|
|
690
|
-
}
|
|
691
|
-
case "USER_ACTION_RESENT": {
|
|
692
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
693
|
-
appendThinkingText(state, "\n" + displayMessage);
|
|
694
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
695
|
-
state.steps.push({
|
|
696
|
-
id: stepId,
|
|
697
|
-
eventType,
|
|
698
|
-
message: displayMessage,
|
|
699
|
-
status: "completed",
|
|
700
637
|
timestamp: Date.now(),
|
|
701
638
|
elapsedMs: event.elapsedMs
|
|
702
639
|
});
|
|
640
|
+
state.currentExecutingStepId = stepId;
|
|
703
641
|
state.lastEventType = eventType;
|
|
704
642
|
break;
|
|
705
643
|
}
|
|
706
|
-
case "
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
eventType,
|
|
719
|
-
message: displayMessage,
|
|
720
|
-
status: "error",
|
|
721
|
-
timestamp: Date.now(),
|
|
722
|
-
elapsedMs: event.elapsedMs
|
|
723
|
-
});
|
|
644
|
+
case "USER_NOTIFICATION": {
|
|
645
|
+
const noteMessage = typeof event.message === "string" && event.message.trim() || message || "";
|
|
646
|
+
const userActionId = typeof event.userActionId === "string" ? event.userActionId : "";
|
|
647
|
+
if (noteMessage || userActionId) {
|
|
648
|
+
const notification = {
|
|
649
|
+
id: userActionId || `note-${state.stepCounter++}`,
|
|
650
|
+
message: noteMessage
|
|
651
|
+
};
|
|
652
|
+
state.notifications.push(notification);
|
|
653
|
+
state.lastNotification = notification;
|
|
654
|
+
if (noteMessage) addThinkingDetail(state, noteMessage);
|
|
655
|
+
}
|
|
724
656
|
state.lastEventType = eventType;
|
|
725
657
|
break;
|
|
726
658
|
}
|
|
@@ -914,21 +846,9 @@ function buildFormattedThinking(steps, allThinkingText) {
|
|
|
914
846
|
if (step.message) parts.push(step.message);
|
|
915
847
|
break;
|
|
916
848
|
case "USER_ACTION_REQUIRED":
|
|
917
|
-
parts.push("**
|
|
849
|
+
parts.push("**Action required**");
|
|
918
850
|
if (step.message) parts.push(step.message);
|
|
919
851
|
break;
|
|
920
|
-
case "USER_ACTION_SUCCESS":
|
|
921
|
-
parts.push(`\u2713 ${step.message || "Verification successful"}`);
|
|
922
|
-
break;
|
|
923
|
-
case "USER_ACTION_REJECTED":
|
|
924
|
-
parts.push(`\u2717 ${step.message || "Verification rejected"}`);
|
|
925
|
-
break;
|
|
926
|
-
case "USER_ACTION_EXPIRED":
|
|
927
|
-
parts.push(`\u2717 ${step.message || "Verification expired"}`);
|
|
928
|
-
break;
|
|
929
|
-
case "USER_ACTION_FAILED":
|
|
930
|
-
parts.push(`\u2717 ${step.message || "Verification failed"}`);
|
|
931
|
-
break;
|
|
932
852
|
}
|
|
933
853
|
}
|
|
934
854
|
return parts.length > 0 ? parts.join("\n") : allThinkingText;
|
|
@@ -1024,6 +944,14 @@ function buildRequestHeaders(config) {
|
|
|
1024
944
|
}
|
|
1025
945
|
|
|
1026
946
|
// src/utils/userActionClient.ts
|
|
947
|
+
var UserActionStaleError = class extends Error {
|
|
948
|
+
constructor(userActionId, message = "User action is no longer actionable") {
|
|
949
|
+
super(message);
|
|
950
|
+
__publicField(this, "userActionId");
|
|
951
|
+
this.name = "UserActionStaleError";
|
|
952
|
+
this.userActionId = userActionId;
|
|
953
|
+
}
|
|
954
|
+
};
|
|
1027
955
|
async function sendUserActionRequest(config, userActionId, action, data) {
|
|
1028
956
|
const url = buildUserActionUrl(config, userActionId, action);
|
|
1029
957
|
const baseHeaders = buildRequestHeaders(config);
|
|
@@ -1034,14 +962,17 @@ async function sendUserActionRequest(config, userActionId, action, data) {
|
|
|
1034
962
|
headers,
|
|
1035
963
|
body: hasBody ? JSON.stringify(data) : void 0
|
|
1036
964
|
});
|
|
965
|
+
if (response.status === 404) {
|
|
966
|
+
throw new UserActionStaleError(userActionId);
|
|
967
|
+
}
|
|
1037
968
|
if (!response.ok) {
|
|
1038
969
|
const errorText = await response.text();
|
|
1039
970
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1040
971
|
}
|
|
1041
972
|
return await response.json();
|
|
1042
973
|
}
|
|
1043
|
-
async function submitUserAction(config, userActionId,
|
|
1044
|
-
return sendUserActionRequest(config, userActionId, "submit",
|
|
974
|
+
async function submitUserAction(config, userActionId, content) {
|
|
975
|
+
return sendUserActionRequest(config, userActionId, "submit", content ?? {});
|
|
1045
976
|
}
|
|
1046
977
|
async function cancelUserAction(config, userActionId) {
|
|
1047
978
|
return sendUserActionRequest(config, userActionId, "cancel");
|
|
@@ -1119,6 +1050,13 @@ var activeStreamStore = {
|
|
|
1119
1050
|
streams.get(key)?.listeners.delete(listener);
|
|
1120
1051
|
};
|
|
1121
1052
|
},
|
|
1053
|
+
// Rename an entry — used when the server assigns a new session ID mid-stream
|
|
1054
|
+
rename(oldKey, newKey) {
|
|
1055
|
+
const entry = streams.get(oldKey);
|
|
1056
|
+
if (!entry) return;
|
|
1057
|
+
streams.set(newKey, entry);
|
|
1058
|
+
streams.delete(oldKey);
|
|
1059
|
+
},
|
|
1122
1060
|
// Explicit user cancel — aborts the controller and removes the entry
|
|
1123
1061
|
abort(key) {
|
|
1124
1062
|
const entry = streams.get(key);
|
|
@@ -1215,15 +1153,11 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1215
1153
|
onEvent: (event) => {
|
|
1216
1154
|
if (abortController.signal.aborted) return;
|
|
1217
1155
|
processStreamEventV2(event, state);
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
eventType,
|
|
1224
|
-
event.message?.trim() || event.errorMessage?.trim() || getEventMessage(event)
|
|
1225
|
-
);
|
|
1226
|
-
callbacksRef.current.onUserActionEvent?.(eventType, msg);
|
|
1156
|
+
if (state.lastUserAction) {
|
|
1157
|
+
callbacksRef.current.onUserActionRequired?.(state.lastUserAction);
|
|
1158
|
+
}
|
|
1159
|
+
if (state.lastNotification) {
|
|
1160
|
+
callbacksRef.current.onUserNotification?.(state.lastNotification);
|
|
1227
1161
|
}
|
|
1228
1162
|
const activeStep = state.steps.find((s) => s.id === state.currentExecutingStepId);
|
|
1229
1163
|
const lastInProgressStep = [...state.steps].reverse().find((s) => s.status === "in_progress");
|
|
@@ -1264,7 +1198,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1264
1198
|
currentExecutingStepId: state.currentExecutingStepId,
|
|
1265
1199
|
executionId: state.executionId,
|
|
1266
1200
|
sessionId: state.sessionId,
|
|
1267
|
-
userActionResult: state.userActionResult,
|
|
1268
1201
|
isCancelled: false
|
|
1269
1202
|
});
|
|
1270
1203
|
}
|
|
@@ -1275,14 +1208,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1275
1208
|
if (error.name !== "AbortError") {
|
|
1276
1209
|
callbacksRef.current.onError?.(error);
|
|
1277
1210
|
}
|
|
1278
|
-
if (state.userActionPending) {
|
|
1279
|
-
state.userActionPending = false;
|
|
1280
|
-
state.userActionRequest = void 0;
|
|
1281
|
-
callbacksRef.current.onUserActionEvent?.(
|
|
1282
|
-
"USER_ACTION_FAILED",
|
|
1283
|
-
"Connection lost. Please try again."
|
|
1284
|
-
);
|
|
1285
|
-
}
|
|
1286
1211
|
const isAborted = error.name === "AbortError";
|
|
1287
1212
|
setMessages(
|
|
1288
1213
|
(prev) => prev.map(
|
|
@@ -1311,14 +1236,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1311
1236
|
setIsWaitingForResponse(false);
|
|
1312
1237
|
callbacksRef.current.onStatusMessage?.(null);
|
|
1313
1238
|
callbacksRef.current.onStepsUpdate?.([]);
|
|
1314
|
-
if (state.userActionPending) {
|
|
1315
|
-
state.userActionPending = false;
|
|
1316
|
-
state.userActionRequest = void 0;
|
|
1317
|
-
callbacksRef.current.onUserActionEvent?.(
|
|
1318
|
-
"USER_ACTION_FAILED",
|
|
1319
|
-
"Verification could not be completed."
|
|
1320
|
-
);
|
|
1321
|
-
}
|
|
1322
1239
|
if (state.sessionId && state.sessionId !== sessionId) {
|
|
1323
1240
|
callbacksRef.current.onSessionIdChange?.(state.sessionId);
|
|
1324
1241
|
}
|
|
@@ -1342,7 +1259,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1342
1259
|
steps: state.hasError ? [] : [...state.steps],
|
|
1343
1260
|
isCancelled: false,
|
|
1344
1261
|
currentExecutingStepId: void 0,
|
|
1345
|
-
userActionResult: state.userActionResult,
|
|
1346
1262
|
formattedThinkingText: state.hasError ? void 0 : state.formattedThinkingText || void 0,
|
|
1347
1263
|
isResolvingImages: needsImageResolve,
|
|
1348
1264
|
totalElapsedMs: state.hasError ? void 0 : state.totalElapsedMs
|
|
@@ -1385,14 +1301,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1385
1301
|
if (error.name !== "AbortError") {
|
|
1386
1302
|
callbacksRef.current.onError?.(error);
|
|
1387
1303
|
}
|
|
1388
|
-
if (state.userActionPending) {
|
|
1389
|
-
state.userActionPending = false;
|
|
1390
|
-
state.userActionRequest = void 0;
|
|
1391
|
-
callbacksRef.current.onUserActionEvent?.(
|
|
1392
|
-
"USER_ACTION_FAILED",
|
|
1393
|
-
"Connection lost. Please try again."
|
|
1394
|
-
);
|
|
1395
|
-
}
|
|
1396
1304
|
const isAborted = error.name === "AbortError";
|
|
1397
1305
|
setMessages(
|
|
1398
1306
|
(prev) => prev.map(
|
|
@@ -1431,8 +1339,23 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1431
1339
|
}
|
|
1432
1340
|
|
|
1433
1341
|
// src/hooks/useChatV2.ts
|
|
1342
|
+
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1343
|
+
function upsertPrompt(prompts, req) {
|
|
1344
|
+
const active = { ...req, status: "pending" };
|
|
1345
|
+
const idx = prompts.findIndex(
|
|
1346
|
+
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
1347
|
+
);
|
|
1348
|
+
if (idx >= 0) {
|
|
1349
|
+
const next = prompts.slice();
|
|
1350
|
+
next[idx] = active;
|
|
1351
|
+
return next;
|
|
1352
|
+
}
|
|
1353
|
+
return [...prompts, active];
|
|
1354
|
+
}
|
|
1434
1355
|
function getStoredOrInitialMessages(config) {
|
|
1435
1356
|
if (!config.userId) return config.initialMessages ?? [];
|
|
1357
|
+
const activeStream = activeStreamStore.get(config.userId);
|
|
1358
|
+
if (activeStream) return activeStream.messages;
|
|
1436
1359
|
const stored = chatStore.get(config.userId);
|
|
1437
1360
|
if (stored.length > 0) return stored;
|
|
1438
1361
|
if (config.initialMessages?.length) {
|
|
@@ -1446,11 +1369,16 @@ function getSessionIdFromMessages(messages) {
|
|
|
1446
1369
|
}
|
|
1447
1370
|
function useChatV2(config, callbacks = {}) {
|
|
1448
1371
|
const [messages, setMessages] = react.useState(() => getStoredOrInitialMessages(config));
|
|
1449
|
-
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(
|
|
1372
|
+
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(() => {
|
|
1373
|
+
if (!config.userId) return false;
|
|
1374
|
+
return activeStreamStore.get(config.userId)?.isWaiting ?? false;
|
|
1375
|
+
});
|
|
1450
1376
|
const sessionIdRef = react.useRef(
|
|
1451
1377
|
getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
|
|
1452
1378
|
);
|
|
1453
1379
|
const prevUserIdRef = react.useRef(config.userId);
|
|
1380
|
+
const streamUserIdRef = react.useRef(void 0);
|
|
1381
|
+
const subscriptionPrevUserIdRef = react.useRef(config.userId);
|
|
1454
1382
|
const callbacksRef = react.useRef(callbacks);
|
|
1455
1383
|
callbacksRef.current = callbacks;
|
|
1456
1384
|
const configRef = react.useRef(config);
|
|
@@ -1459,33 +1387,35 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1459
1387
|
messagesRef.current = messages;
|
|
1460
1388
|
const storeAwareSetMessages = react.useCallback(
|
|
1461
1389
|
(updater) => {
|
|
1462
|
-
const
|
|
1463
|
-
|
|
1464
|
-
|
|
1390
|
+
const streamUserId = streamUserIdRef.current;
|
|
1391
|
+
const currentUserId = configRef.current.userId;
|
|
1392
|
+
const storeKey = streamUserId ?? currentUserId;
|
|
1393
|
+
if (storeKey && activeStreamStore.has(storeKey)) {
|
|
1394
|
+
activeStreamStore.applyMessages(storeKey, updater);
|
|
1395
|
+
}
|
|
1396
|
+
if (!streamUserId || streamUserId === currentUserId) {
|
|
1397
|
+
setMessages(updater);
|
|
1465
1398
|
}
|
|
1466
|
-
setMessages(updater);
|
|
1467
1399
|
},
|
|
1468
1400
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1469
1401
|
[]
|
|
1470
1402
|
);
|
|
1471
1403
|
const storeAwareSetIsWaiting = react.useCallback(
|
|
1472
1404
|
(waiting) => {
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1475
|
-
|
|
1405
|
+
const streamUserId = streamUserIdRef.current;
|
|
1406
|
+
const currentUserId = configRef.current.userId;
|
|
1407
|
+
const storeKey = streamUserId ?? currentUserId;
|
|
1408
|
+
if (storeKey && activeStreamStore.has(storeKey)) {
|
|
1409
|
+
activeStreamStore.setWaiting(storeKey, waiting);
|
|
1410
|
+
}
|
|
1411
|
+
if (!streamUserId || streamUserId === currentUserId) {
|
|
1412
|
+
setIsWaitingForResponse(waiting);
|
|
1476
1413
|
}
|
|
1477
|
-
setIsWaitingForResponse(waiting);
|
|
1478
1414
|
},
|
|
1479
1415
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1480
1416
|
[]
|
|
1481
1417
|
);
|
|
1482
|
-
const [userActionState, setUserActionState] = react.useState(
|
|
1483
|
-
request: null,
|
|
1484
|
-
result: null,
|
|
1485
|
-
clearOtpTrigger: 0
|
|
1486
|
-
});
|
|
1487
|
-
const userActionStateRef = react.useRef(userActionState);
|
|
1488
|
-
userActionStateRef.current = userActionState;
|
|
1418
|
+
const [userActionState, setUserActionState] = react.useState(EMPTY_USER_ACTION_STATE);
|
|
1489
1419
|
const wrappedCallbacks = react.useMemo(() => ({
|
|
1490
1420
|
...callbacksRef.current,
|
|
1491
1421
|
onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
|
|
@@ -1495,26 +1425,17 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1495
1425
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1496
1426
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1497
1427
|
onUserActionRequired: (request) => {
|
|
1498
|
-
setUserActionState((prev) => ({
|
|
1428
|
+
setUserActionState((prev) => ({
|
|
1429
|
+
...prev,
|
|
1430
|
+
prompts: upsertPrompt(prev.prompts, request)
|
|
1431
|
+
}));
|
|
1499
1432
|
callbacksRef.current.onUserActionRequired?.(request);
|
|
1500
1433
|
},
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
case "USER_ACTION_REJECTED":
|
|
1507
|
-
setUserActionState((prev) => ({ ...prev, request: null, result: "rejected" }));
|
|
1508
|
-
break;
|
|
1509
|
-
case "USER_ACTION_EXPIRED":
|
|
1510
|
-
case "USER_ACTION_FAILED":
|
|
1511
|
-
setUserActionState((prev) => ({ ...prev, request: null }));
|
|
1512
|
-
break;
|
|
1513
|
-
case "USER_ACTION_INVALID":
|
|
1514
|
-
setUserActionState((prev) => ({ ...prev, clearOtpTrigger: prev.clearOtpTrigger + 1 }));
|
|
1515
|
-
break;
|
|
1516
|
-
}
|
|
1517
|
-
callbacksRef.current.onUserActionEvent?.(eventType, message);
|
|
1434
|
+
onUserNotification: (notification) => {
|
|
1435
|
+
setUserActionState(
|
|
1436
|
+
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1437
|
+
);
|
|
1438
|
+
callbacksRef.current.onUserNotification?.(notification);
|
|
1518
1439
|
}
|
|
1519
1440
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1520
1441
|
}), []);
|
|
@@ -1562,6 +1483,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1562
1483
|
const abortController = new AbortController();
|
|
1563
1484
|
const { userId } = configRef.current;
|
|
1564
1485
|
if (userId) {
|
|
1486
|
+
streamUserIdRef.current = userId;
|
|
1565
1487
|
const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
|
|
1566
1488
|
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1567
1489
|
}
|
|
@@ -1572,9 +1494,11 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1572
1494
|
abortController,
|
|
1573
1495
|
options
|
|
1574
1496
|
);
|
|
1575
|
-
|
|
1576
|
-
|
|
1497
|
+
const finalStreamUserId = streamUserIdRef.current ?? userId;
|
|
1498
|
+
if (finalStreamUserId) {
|
|
1499
|
+
activeStreamStore.complete(finalStreamUserId);
|
|
1577
1500
|
}
|
|
1501
|
+
streamUserIdRef.current = void 0;
|
|
1578
1502
|
if (!abortController.signal.aborted && newSessionId && newSessionId !== sessionIdRef.current) {
|
|
1579
1503
|
sessionIdRef.current = newSessionId;
|
|
1580
1504
|
}
|
|
@@ -1591,12 +1515,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1591
1515
|
setMessages((prev) => [...msgs, ...prev]);
|
|
1592
1516
|
}, []);
|
|
1593
1517
|
const cancelStream = react.useCallback(() => {
|
|
1594
|
-
|
|
1595
|
-
|
|
1518
|
+
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1519
|
+
if (streamUserId) {
|
|
1520
|
+
activeStreamStore.abort(streamUserId);
|
|
1596
1521
|
}
|
|
1522
|
+
streamUserIdRef.current = void 0;
|
|
1597
1523
|
cancelStreamManager();
|
|
1598
1524
|
setIsWaitingForResponse(false);
|
|
1599
|
-
setUserActionState((prev) => ({ ...prev,
|
|
1525
|
+
setUserActionState((prev) => ({ ...prev, prompts: [] }));
|
|
1600
1526
|
setMessages(
|
|
1601
1527
|
(prev) => prev.map((msg) => {
|
|
1602
1528
|
if (msg.isStreaming) {
|
|
@@ -1613,15 +1539,19 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1613
1539
|
);
|
|
1614
1540
|
}, [cancelStreamManager]);
|
|
1615
1541
|
const resetSession = react.useCallback(() => {
|
|
1542
|
+
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1543
|
+
if (streamUserId) {
|
|
1544
|
+
activeStreamStore.abort(streamUserId);
|
|
1545
|
+
}
|
|
1616
1546
|
if (configRef.current.userId) {
|
|
1617
|
-
activeStreamStore.abort(configRef.current.userId);
|
|
1618
1547
|
chatStore.delete(configRef.current.userId);
|
|
1619
1548
|
}
|
|
1549
|
+
streamUserIdRef.current = void 0;
|
|
1620
1550
|
setMessages([]);
|
|
1621
1551
|
sessionIdRef.current = void 0;
|
|
1622
1552
|
abortControllerRef.current?.abort();
|
|
1623
1553
|
setIsWaitingForResponse(false);
|
|
1624
|
-
setUserActionState(
|
|
1554
|
+
setUserActionState(EMPTY_USER_ACTION_STATE);
|
|
1625
1555
|
}, []);
|
|
1626
1556
|
const getSessionId = react.useCallback(() => {
|
|
1627
1557
|
return sessionIdRef.current;
|
|
@@ -1629,59 +1559,91 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1629
1559
|
const getMessages = react.useCallback(() => {
|
|
1630
1560
|
return messages;
|
|
1631
1561
|
}, [messages]);
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1562
|
+
const setPromptStatus = react.useCallback(
|
|
1563
|
+
(userActionId, status) => {
|
|
1564
|
+
setUserActionState((prev) => ({
|
|
1565
|
+
...prev,
|
|
1566
|
+
prompts: prev.prompts.map(
|
|
1567
|
+
(p) => p.userActionId === userActionId ? { ...p, status } : p
|
|
1568
|
+
)
|
|
1569
|
+
}));
|
|
1570
|
+
},
|
|
1571
|
+
[]
|
|
1572
|
+
);
|
|
1573
|
+
const removePrompt = react.useCallback((userActionId) => {
|
|
1574
|
+
setUserActionState((prev) => ({
|
|
1575
|
+
...prev,
|
|
1576
|
+
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
1577
|
+
}));
|
|
1578
|
+
}, []);
|
|
1579
|
+
const submitUserAction2 = react.useCallback(
|
|
1580
|
+
async (userActionId, content) => {
|
|
1581
|
+
setPromptStatus(userActionId, "submitting");
|
|
1636
1582
|
try {
|
|
1637
|
-
await submitUserAction(configRef.current,
|
|
1583
|
+
await submitUserAction(configRef.current, userActionId, content);
|
|
1584
|
+
removePrompt(userActionId);
|
|
1638
1585
|
} catch (error) {
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
}
|
|
1586
|
+
if (error instanceof UserActionStaleError) {
|
|
1587
|
+
setPromptStatus(userActionId, "stale");
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
setPromptStatus(userActionId, "pending");
|
|
1643
1591
|
callbacksRef.current.onError?.(error);
|
|
1644
1592
|
throw error;
|
|
1645
1593
|
}
|
|
1646
1594
|
},
|
|
1647
|
-
[]
|
|
1595
|
+
[removePrompt, setPromptStatus]
|
|
1648
1596
|
);
|
|
1649
|
-
const
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
}
|
|
1597
|
+
const cancelUserAction2 = react.useCallback(
|
|
1598
|
+
async (userActionId) => {
|
|
1599
|
+
setPromptStatus(userActionId, "submitting");
|
|
1600
|
+
try {
|
|
1601
|
+
await cancelUserAction(configRef.current, userActionId);
|
|
1602
|
+
removePrompt(userActionId);
|
|
1603
|
+
} catch (error) {
|
|
1604
|
+
if (error instanceof UserActionStaleError) {
|
|
1605
|
+
removePrompt(userActionId);
|
|
1606
|
+
return;
|
|
1660
1607
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1608
|
+
setPromptStatus(userActionId, "pending");
|
|
1609
|
+
callbacksRef.current.onError?.(error);
|
|
1610
|
+
throw error;
|
|
1611
|
+
}
|
|
1612
|
+
},
|
|
1613
|
+
[removePrompt, setPromptStatus]
|
|
1614
|
+
);
|
|
1615
|
+
const resendUserAction2 = react.useCallback(
|
|
1616
|
+
async (userActionId) => {
|
|
1617
|
+
setPromptStatus(userActionId, "submitting");
|
|
1618
|
+
try {
|
|
1619
|
+
await resendUserAction(configRef.current, userActionId);
|
|
1620
|
+
setPromptStatus(userActionId, "pending");
|
|
1621
|
+
} catch (error) {
|
|
1622
|
+
if (error instanceof UserActionStaleError) {
|
|
1623
|
+
setPromptStatus(userActionId, "stale");
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
setPromptStatus(userActionId, "pending");
|
|
1627
|
+
callbacksRef.current.onError?.(error);
|
|
1628
|
+
throw error;
|
|
1629
|
+
}
|
|
1630
|
+
},
|
|
1631
|
+
[setPromptStatus]
|
|
1632
|
+
);
|
|
1633
|
+
const dismissNotification = react.useCallback((id) => {
|
|
1634
|
+
setUserActionState((prev) => ({
|
|
1635
|
+
...prev,
|
|
1636
|
+
notifications: prev.notifications.filter((n) => n.id !== id)
|
|
1637
|
+
}));
|
|
1681
1638
|
}, []);
|
|
1682
1639
|
react.useEffect(() => {
|
|
1640
|
+
const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
|
|
1641
|
+
subscriptionPrevUserIdRef.current = config.userId;
|
|
1683
1642
|
const { userId } = config;
|
|
1684
1643
|
if (!userId) return;
|
|
1644
|
+
if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
|
|
1645
|
+
streamUserIdRef.current = userId;
|
|
1646
|
+
}
|
|
1685
1647
|
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
|
|
1686
1648
|
setMessages(msgs);
|
|
1687
1649
|
setIsWaitingForResponse(isWaiting);
|
|
@@ -1695,6 +1657,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1695
1657
|
}, [config.userId]);
|
|
1696
1658
|
react.useEffect(() => {
|
|
1697
1659
|
if (!config.userId) return;
|
|
1660
|
+
if (prevUserIdRef.current !== config.userId) return;
|
|
1698
1661
|
const toSave = messages.filter((m) => !m.isStreaming);
|
|
1699
1662
|
if (toSave.length > 0) {
|
|
1700
1663
|
chatStore.set(config.userId, toSave);
|
|
@@ -1716,7 +1679,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1716
1679
|
setMessages([]);
|
|
1717
1680
|
sessionIdRef.current = void 0;
|
|
1718
1681
|
setIsWaitingForResponse(false);
|
|
1719
|
-
setUserActionState(
|
|
1682
|
+
setUserActionState(EMPTY_USER_ACTION_STATE);
|
|
1720
1683
|
} else if (config.userId) {
|
|
1721
1684
|
const active = activeStreamStore.get(config.userId);
|
|
1722
1685
|
if (active) {
|
|
@@ -1743,9 +1706,10 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1743
1706
|
isWaitingForResponse,
|
|
1744
1707
|
sessionId: sessionIdRef.current,
|
|
1745
1708
|
userActionState,
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1709
|
+
submitUserAction: submitUserAction2,
|
|
1710
|
+
cancelUserAction: cancelUserAction2,
|
|
1711
|
+
resendUserAction: resendUserAction2,
|
|
1712
|
+
dismissNotification
|
|
1749
1713
|
};
|
|
1750
1714
|
}
|
|
1751
1715
|
function getSpeechRecognition() {
|
|
@@ -1964,15 +1928,151 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1964
1928
|
};
|
|
1965
1929
|
}
|
|
1966
1930
|
|
|
1931
|
+
// src/utils/jsonSchemaForm.ts
|
|
1932
|
+
function classifyField(field) {
|
|
1933
|
+
if (!field) return "text";
|
|
1934
|
+
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
1935
|
+
switch (field.type) {
|
|
1936
|
+
case "boolean":
|
|
1937
|
+
return "boolean";
|
|
1938
|
+
case "integer":
|
|
1939
|
+
return "integer";
|
|
1940
|
+
case "number":
|
|
1941
|
+
return "decimal";
|
|
1942
|
+
case "string":
|
|
1943
|
+
return "text";
|
|
1944
|
+
default:
|
|
1945
|
+
return "text";
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
function isNestedOrUnsupported(field) {
|
|
1949
|
+
if (!field) return false;
|
|
1950
|
+
if (field.type === "object" || field.type === "array") return true;
|
|
1951
|
+
if ("properties" in field && field.properties != null) return true;
|
|
1952
|
+
if ("items" in field && field.items != null) return true;
|
|
1953
|
+
return false;
|
|
1954
|
+
}
|
|
1955
|
+
function getOptions(field) {
|
|
1956
|
+
if (!field || !Array.isArray(field.oneOf)) return [];
|
|
1957
|
+
return field.oneOf.filter(
|
|
1958
|
+
(o) => !!o && typeof o === "object" && typeof o.const === "string"
|
|
1959
|
+
);
|
|
1960
|
+
}
|
|
1961
|
+
function isRequired(schema, key) {
|
|
1962
|
+
return Array.isArray(schema?.required) && schema.required.includes(key);
|
|
1963
|
+
}
|
|
1964
|
+
function coerceValue(field, raw) {
|
|
1965
|
+
const widget = classifyField(field);
|
|
1966
|
+
if (widget === "boolean") {
|
|
1967
|
+
if (typeof raw === "boolean") return raw;
|
|
1968
|
+
if (raw === "true") return true;
|
|
1969
|
+
if (raw === "false") return false;
|
|
1970
|
+
return Boolean(raw);
|
|
1971
|
+
}
|
|
1972
|
+
if (widget === "integer" || widget === "decimal") {
|
|
1973
|
+
if (raw === "" || raw == null) return void 0;
|
|
1974
|
+
const num = typeof raw === "number" ? raw : Number(String(raw).trim());
|
|
1975
|
+
if (Number.isNaN(num)) return void 0;
|
|
1976
|
+
return widget === "integer" ? Math.trunc(num) : num;
|
|
1977
|
+
}
|
|
1978
|
+
if (raw == null) return void 0;
|
|
1979
|
+
const str = String(raw);
|
|
1980
|
+
return str === "" ? void 0 : str;
|
|
1981
|
+
}
|
|
1982
|
+
function defaultValueFor(field) {
|
|
1983
|
+
if (!field || field.default === void 0) {
|
|
1984
|
+
return classifyField(field) === "boolean" ? false : "";
|
|
1985
|
+
}
|
|
1986
|
+
return field.default;
|
|
1987
|
+
}
|
|
1988
|
+
function validateField(field, value, required) {
|
|
1989
|
+
const widget = classifyField(field);
|
|
1990
|
+
const label = field?.title || "This field";
|
|
1991
|
+
const isEmpty = value === void 0 || value === null || typeof value === "string" && value.trim() === "";
|
|
1992
|
+
if (isEmpty) {
|
|
1993
|
+
if (required && widget !== "boolean") return `${label} is required.`;
|
|
1994
|
+
return null;
|
|
1995
|
+
}
|
|
1996
|
+
if (widget === "integer" || widget === "decimal") {
|
|
1997
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
1998
|
+
if (Number.isNaN(num)) return `${label} must be a number.`;
|
|
1999
|
+
if (widget === "integer" && !Number.isInteger(num)) {
|
|
2000
|
+
return `${label} must be a whole number.`;
|
|
2001
|
+
}
|
|
2002
|
+
if (typeof field?.minimum === "number" && num < field.minimum) {
|
|
2003
|
+
return `${label} must be at least ${field.minimum}.`;
|
|
2004
|
+
}
|
|
2005
|
+
if (typeof field?.maximum === "number" && num > field.maximum) {
|
|
2006
|
+
return `${label} must be at most ${field.maximum}.`;
|
|
2007
|
+
}
|
|
2008
|
+
return null;
|
|
2009
|
+
}
|
|
2010
|
+
if (widget === "select") {
|
|
2011
|
+
const allowed = getOptions(field).map((o) => o.const);
|
|
2012
|
+
if (allowed.length > 0 && !allowed.includes(String(value))) {
|
|
2013
|
+
return `${label} has an invalid selection.`;
|
|
2014
|
+
}
|
|
2015
|
+
return null;
|
|
2016
|
+
}
|
|
2017
|
+
const str = String(value);
|
|
2018
|
+
if (typeof field?.minLength === "number" && str.length < field.minLength) {
|
|
2019
|
+
return `${label} must be at least ${field.minLength} characters.`;
|
|
2020
|
+
}
|
|
2021
|
+
if (typeof field?.maxLength === "number" && str.length > field.maxLength) {
|
|
2022
|
+
return `${label} must be at most ${field.maxLength} characters.`;
|
|
2023
|
+
}
|
|
2024
|
+
return null;
|
|
2025
|
+
}
|
|
2026
|
+
function renderableFields(schema) {
|
|
2027
|
+
const props = schema?.properties;
|
|
2028
|
+
if (!props) return [];
|
|
2029
|
+
return Object.entries(props).filter(([, field]) => !isNestedOrUnsupported(field));
|
|
2030
|
+
}
|
|
2031
|
+
function validateForm(schema, values) {
|
|
2032
|
+
const errors = {};
|
|
2033
|
+
for (const [key, field] of renderableFields(schema)) {
|
|
2034
|
+
const coerced = coerceValue(field, values[key]);
|
|
2035
|
+
const err = validateField(field, coerced, isRequired(schema, key));
|
|
2036
|
+
if (err) errors[key] = err;
|
|
2037
|
+
}
|
|
2038
|
+
return errors;
|
|
2039
|
+
}
|
|
2040
|
+
function buildContent(schema, values) {
|
|
2041
|
+
const content = {};
|
|
2042
|
+
for (const [key, field] of renderableFields(schema)) {
|
|
2043
|
+
const coerced = coerceValue(field, values[key]);
|
|
2044
|
+
if (coerced !== void 0) content[key] = coerced;
|
|
2045
|
+
}
|
|
2046
|
+
return content;
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
// src/index.ts
|
|
2050
|
+
function migrateActiveStream(oldUserId, newUserId) {
|
|
2051
|
+
activeStreamStore.rename(oldUserId, newUserId);
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
exports.UserActionStaleError = UserActionStaleError;
|
|
2055
|
+
exports.buildContent = buildContent;
|
|
1967
2056
|
exports.buildFormattedThinking = buildFormattedThinking;
|
|
1968
2057
|
exports.cancelUserAction = cancelUserAction;
|
|
2058
|
+
exports.classifyField = classifyField;
|
|
2059
|
+
exports.classifyUserActionKind = classifyUserActionKind;
|
|
2060
|
+
exports.coerceValue = coerceValue;
|
|
1969
2061
|
exports.createInitialV2State = createInitialV2State;
|
|
2062
|
+
exports.defaultValueFor = defaultValueFor;
|
|
1970
2063
|
exports.generateId = generateId;
|
|
2064
|
+
exports.getOptions = getOptions;
|
|
2065
|
+
exports.isNestedOrUnsupported = isNestedOrUnsupported;
|
|
2066
|
+
exports.isRequired = isRequired;
|
|
2067
|
+
exports.migrateActiveStream = migrateActiveStream;
|
|
1971
2068
|
exports.processStreamEventV2 = processStreamEventV2;
|
|
2069
|
+
exports.renderableFields = renderableFields;
|
|
1972
2070
|
exports.resendUserAction = resendUserAction;
|
|
1973
2071
|
exports.streamWorkflowEvents = streamWorkflowEvents;
|
|
1974
2072
|
exports.submitUserAction = submitUserAction;
|
|
1975
2073
|
exports.useChatV2 = useChatV2;
|
|
1976
2074
|
exports.useVoice = useVoice;
|
|
2075
|
+
exports.validateField = validateField;
|
|
2076
|
+
exports.validateForm = validateForm;
|
|
1977
2077
|
//# sourceMappingURL=index.js.map
|
|
1978
2078
|
//# sourceMappingURL=index.js.map
|