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