@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.native.js
CHANGED
|
@@ -4,7 +4,9 @@ var react = require('react');
|
|
|
4
4
|
var reactNativeMmkv = require('react-native-mmkv');
|
|
5
5
|
var expoSpeechRecognition = require('expo-speech-recognition');
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
|
|
8
10
|
|
|
9
11
|
// src/utils/generateId.ts
|
|
10
12
|
function generateId() {
|
|
@@ -275,31 +277,27 @@ function normalizeEvent(event) {
|
|
|
275
277
|
return event;
|
|
276
278
|
}
|
|
277
279
|
}
|
|
278
|
-
function
|
|
279
|
-
|
|
280
|
+
function isVerificationSchema(schema) {
|
|
281
|
+
const props = schema?.properties;
|
|
282
|
+
if (!props) return false;
|
|
283
|
+
const keys = Object.keys(props);
|
|
284
|
+
return keys.length === 1 && keys[0] === "verificationCode";
|
|
280
285
|
}
|
|
281
|
-
function
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
case "
|
|
286
|
-
return
|
|
287
|
-
case "
|
|
288
|
-
return
|
|
289
|
-
case "USER_ACTION_INVALID":
|
|
290
|
-
return safeRaw || "Invalid code. Please try again.";
|
|
291
|
-
case "USER_ACTION_REJECTED":
|
|
292
|
-
return safeRaw || "Verification cancelled";
|
|
293
|
-
case "USER_ACTION_EXPIRED":
|
|
294
|
-
return safeRaw || "Verification expired";
|
|
295
|
-
case "USER_ACTION_RESENT":
|
|
296
|
-
return safeRaw || "Verification code resent";
|
|
297
|
-
case "USER_ACTION_FAILED":
|
|
298
|
-
return safeRaw || "Verification failed";
|
|
286
|
+
function classifyUserActionKind(action, schema) {
|
|
287
|
+
switch ((action || "").toLowerCase()) {
|
|
288
|
+
case "userverificationrequest":
|
|
289
|
+
return "verification";
|
|
290
|
+
case "usernotificationrequest":
|
|
291
|
+
return "notification";
|
|
292
|
+
case "userformrequest":
|
|
293
|
+
return isVerificationSchema(schema) ? "verification" : "form";
|
|
299
294
|
default:
|
|
300
|
-
return
|
|
295
|
+
return isVerificationSchema(schema) ? "verification" : "form";
|
|
301
296
|
}
|
|
302
297
|
}
|
|
298
|
+
function userActionHeader(kind) {
|
|
299
|
+
return kind === "verification" ? "**Verification required**" : "**Action required**";
|
|
300
|
+
}
|
|
303
301
|
function workingPhaseDetailForDisplay(raw) {
|
|
304
302
|
const t = raw.trim();
|
|
305
303
|
if (!t) return "";
|
|
@@ -359,18 +357,32 @@ function createInitialV2State() {
|
|
|
359
357
|
executionId: void 0,
|
|
360
358
|
hasError: false,
|
|
361
359
|
errorMessage: "",
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
360
|
+
userActions: [],
|
|
361
|
+
notifications: [],
|
|
362
|
+
lastUserAction: void 0,
|
|
363
|
+
lastNotification: void 0,
|
|
365
364
|
finalData: void 0,
|
|
366
365
|
steps: [],
|
|
367
366
|
stepCounter: 0,
|
|
368
367
|
currentExecutingStepId: void 0
|
|
369
368
|
};
|
|
370
369
|
}
|
|
370
|
+
function upsertUserAction(state, req) {
|
|
371
|
+
const active = { ...req, status: "pending" };
|
|
372
|
+
const matchIdx = state.userActions.findIndex(
|
|
373
|
+
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
374
|
+
);
|
|
375
|
+
if (matchIdx >= 0) {
|
|
376
|
+
state.userActions[matchIdx] = active;
|
|
377
|
+
} else {
|
|
378
|
+
state.userActions.push(active);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
371
381
|
function processStreamEventV2(rawEvent, state) {
|
|
372
382
|
const event = normalizeEvent(rawEvent);
|
|
373
383
|
const eventType = event.eventType;
|
|
384
|
+
state.lastUserAction = void 0;
|
|
385
|
+
state.lastNotification = void 0;
|
|
374
386
|
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
375
387
|
if (event.executionId) state.executionId = event.executionId;
|
|
376
388
|
if (event.sessionId) state.sessionId = event.sessionId;
|
|
@@ -592,152 +604,72 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
592
604
|
break;
|
|
593
605
|
}
|
|
594
606
|
case "USER_ACTION_REQUIRED": {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
607
|
+
const rawAction = typeof event.action === "string" ? event.action : void 0;
|
|
608
|
+
const schema = event.requestedSchema;
|
|
609
|
+
const kind = classifyUserActionKind(rawAction, schema);
|
|
610
|
+
const promptMessage = typeof event.message === "string" && event.message.trim() || message || "";
|
|
611
|
+
const userActionId = typeof event.userActionId === "string" ? event.userActionId : "";
|
|
612
|
+
if (kind === "notification") {
|
|
613
|
+
const notification = {
|
|
614
|
+
id: userActionId || `note-${state.stepCounter++}`,
|
|
615
|
+
message: promptMessage
|
|
603
616
|
};
|
|
617
|
+
state.notifications.push(notification);
|
|
618
|
+
state.lastNotification = notification;
|
|
619
|
+
if (promptMessage) addThinkingDetail(state, promptMessage);
|
|
620
|
+
state.lastEventType = eventType;
|
|
621
|
+
break;
|
|
604
622
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
eventType,
|
|
609
|
-
req?.message || message
|
|
610
|
-
);
|
|
611
|
-
if (req) {
|
|
612
|
-
addThinkingLine(state, "**Verification Required**", displayMessage);
|
|
623
|
+
if (!userActionId) {
|
|
624
|
+
state.lastEventType = eventType;
|
|
625
|
+
break;
|
|
613
626
|
}
|
|
614
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
615
|
-
state.steps.push({
|
|
616
|
-
id: stepId,
|
|
617
|
-
eventType,
|
|
618
|
-
message: displayMessage,
|
|
619
|
-
status: "in_progress",
|
|
620
|
-
timestamp: Date.now(),
|
|
621
|
-
elapsedMs: event.elapsedMs
|
|
622
|
-
});
|
|
623
|
-
state.currentExecutingStepId = stepId;
|
|
624
|
-
state.lastEventType = eventType;
|
|
625
|
-
break;
|
|
626
|
-
}
|
|
627
|
-
case "USER_ACTION_SUCCESS": {
|
|
628
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
629
|
-
appendThinkingText(state, "\n\u2713 " + displayMessage);
|
|
630
627
|
completeLastInProgressStep(state.steps);
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
628
|
+
const verificationType = event.verificationType === "ALPHANUMERIC_CODE" || event.verificationType === "NUMERIC_CODE" ? event.verificationType : void 0;
|
|
629
|
+
const request = {
|
|
630
|
+
userActionId,
|
|
631
|
+
kind,
|
|
632
|
+
rawAction,
|
|
633
|
+
subAction: typeof event.subAction === "string" ? event.subAction : void 0,
|
|
634
|
+
verificationType,
|
|
635
|
+
expirySeconds: typeof event.expirySeconds === "number" ? event.expirySeconds : void 0,
|
|
636
|
+
message: promptMessage || void 0,
|
|
637
|
+
requestedSchema: schema,
|
|
638
|
+
metadata: event.metadata,
|
|
639
|
+
toolCallId: typeof event.toolCallId === "string" ? event.toolCallId : void 0,
|
|
640
|
+
executionId: state.executionId,
|
|
641
|
+
sessionId: state.sessionId
|
|
642
|
+
};
|
|
643
|
+
upsertUserAction(state, request);
|
|
644
|
+
state.lastUserAction = request;
|
|
645
|
+
const header = userActionHeader(kind);
|
|
646
|
+
if (promptMessage) addThinkingLine(state, header, promptMessage);
|
|
647
|
+
else addThinkingHeader(state, header);
|
|
634
648
|
const stepId = `step-${state.stepCounter++}`;
|
|
635
649
|
state.steps.push({
|
|
636
650
|
id: stepId,
|
|
637
651
|
eventType,
|
|
638
|
-
message:
|
|
639
|
-
status: "completed",
|
|
640
|
-
timestamp: Date.now(),
|
|
641
|
-
elapsedMs: event.elapsedMs
|
|
642
|
-
});
|
|
643
|
-
state.lastEventType = eventType;
|
|
644
|
-
break;
|
|
645
|
-
}
|
|
646
|
-
case "USER_ACTION_INVALID": {
|
|
647
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
648
|
-
appendThinkingText(state, "\n\u2717 " + displayMessage);
|
|
649
|
-
completeLastInProgressStep(state.steps);
|
|
650
|
-
const errorStepId = `step-${state.stepCounter++}`;
|
|
651
|
-
state.steps.push({
|
|
652
|
-
id: errorStepId,
|
|
653
|
-
eventType,
|
|
654
|
-
message: displayMessage,
|
|
655
|
-
status: "error",
|
|
656
|
-
timestamp: Date.now(),
|
|
657
|
-
elapsedMs: event.elapsedMs
|
|
658
|
-
});
|
|
659
|
-
const retryStepId = `step-${state.stepCounter++}`;
|
|
660
|
-
state.steps.push({
|
|
661
|
-
id: retryStepId,
|
|
662
|
-
eventType: "USER_ACTION_REQUIRED",
|
|
663
|
-
message: "Waiting for verification...",
|
|
652
|
+
message: promptMessage || (kind === "verification" ? "Waiting for verification..." : "Waiting for your input..."),
|
|
664
653
|
status: "in_progress",
|
|
665
|
-
timestamp: Date.now()
|
|
666
|
-
});
|
|
667
|
-
state.currentExecutingStepId = retryStepId;
|
|
668
|
-
state.lastEventType = eventType;
|
|
669
|
-
break;
|
|
670
|
-
}
|
|
671
|
-
case "USER_ACTION_REJECTED": {
|
|
672
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
673
|
-
appendThinkingText(state, "\n" + displayMessage);
|
|
674
|
-
completeLastInProgressStep(state.steps);
|
|
675
|
-
state.userActionRequest = void 0;
|
|
676
|
-
state.userActionPending = false;
|
|
677
|
-
state.userActionResult = "rejected";
|
|
678
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
679
|
-
state.steps.push({
|
|
680
|
-
id: stepId,
|
|
681
|
-
eventType,
|
|
682
|
-
message: displayMessage,
|
|
683
|
-
status: "completed",
|
|
684
|
-
timestamp: Date.now(),
|
|
685
|
-
elapsedMs: event.elapsedMs
|
|
686
|
-
});
|
|
687
|
-
state.lastEventType = eventType;
|
|
688
|
-
break;
|
|
689
|
-
}
|
|
690
|
-
case "USER_ACTION_EXPIRED": {
|
|
691
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
692
|
-
appendThinkingText(state, "\n\u2717 " + displayMessage);
|
|
693
|
-
completeLastInProgressStep(state.steps);
|
|
694
|
-
state.userActionRequest = void 0;
|
|
695
|
-
state.userActionPending = false;
|
|
696
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
697
|
-
state.steps.push({
|
|
698
|
-
id: stepId,
|
|
699
|
-
eventType,
|
|
700
|
-
message: displayMessage,
|
|
701
|
-
status: "error",
|
|
702
|
-
timestamp: Date.now(),
|
|
703
|
-
elapsedMs: event.elapsedMs
|
|
704
|
-
});
|
|
705
|
-
state.lastEventType = eventType;
|
|
706
|
-
break;
|
|
707
|
-
}
|
|
708
|
-
case "USER_ACTION_RESENT": {
|
|
709
|
-
const displayMessage = getUserActionDisplayMessage(eventType, event.message);
|
|
710
|
-
appendThinkingText(state, "\n" + displayMessage);
|
|
711
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
712
|
-
state.steps.push({
|
|
713
|
-
id: stepId,
|
|
714
|
-
eventType,
|
|
715
|
-
message: displayMessage,
|
|
716
|
-
status: "completed",
|
|
717
654
|
timestamp: Date.now(),
|
|
718
655
|
elapsedMs: event.elapsedMs
|
|
719
656
|
});
|
|
657
|
+
state.currentExecutingStepId = stepId;
|
|
720
658
|
state.lastEventType = eventType;
|
|
721
659
|
break;
|
|
722
660
|
}
|
|
723
|
-
case "
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
eventType,
|
|
736
|
-
message: displayMessage,
|
|
737
|
-
status: "error",
|
|
738
|
-
timestamp: Date.now(),
|
|
739
|
-
elapsedMs: event.elapsedMs
|
|
740
|
-
});
|
|
661
|
+
case "USER_NOTIFICATION": {
|
|
662
|
+
const noteMessage = typeof event.message === "string" && event.message.trim() || message || "";
|
|
663
|
+
const userActionId = typeof event.userActionId === "string" ? event.userActionId : "";
|
|
664
|
+
if (noteMessage || userActionId) {
|
|
665
|
+
const notification = {
|
|
666
|
+
id: userActionId || `note-${state.stepCounter++}`,
|
|
667
|
+
message: noteMessage
|
|
668
|
+
};
|
|
669
|
+
state.notifications.push(notification);
|
|
670
|
+
state.lastNotification = notification;
|
|
671
|
+
if (noteMessage) addThinkingDetail(state, noteMessage);
|
|
672
|
+
}
|
|
741
673
|
state.lastEventType = eventType;
|
|
742
674
|
break;
|
|
743
675
|
}
|
|
@@ -931,21 +863,9 @@ function buildFormattedThinking(steps, allThinkingText) {
|
|
|
931
863
|
if (step.message) parts.push(step.message);
|
|
932
864
|
break;
|
|
933
865
|
case "USER_ACTION_REQUIRED":
|
|
934
|
-
parts.push("**
|
|
866
|
+
parts.push("**Action required**");
|
|
935
867
|
if (step.message) parts.push(step.message);
|
|
936
868
|
break;
|
|
937
|
-
case "USER_ACTION_SUCCESS":
|
|
938
|
-
parts.push(`\u2713 ${step.message || "Verification successful"}`);
|
|
939
|
-
break;
|
|
940
|
-
case "USER_ACTION_REJECTED":
|
|
941
|
-
parts.push(`\u2717 ${step.message || "Verification rejected"}`);
|
|
942
|
-
break;
|
|
943
|
-
case "USER_ACTION_EXPIRED":
|
|
944
|
-
parts.push(`\u2717 ${step.message || "Verification expired"}`);
|
|
945
|
-
break;
|
|
946
|
-
case "USER_ACTION_FAILED":
|
|
947
|
-
parts.push(`\u2717 ${step.message || "Verification failed"}`);
|
|
948
|
-
break;
|
|
949
869
|
}
|
|
950
870
|
}
|
|
951
871
|
return parts.length > 0 ? parts.join("\n") : allThinkingText;
|
|
@@ -1041,6 +961,14 @@ function buildRequestHeaders(config) {
|
|
|
1041
961
|
}
|
|
1042
962
|
|
|
1043
963
|
// src/utils/userActionClient.ts
|
|
964
|
+
var UserActionStaleError = class extends Error {
|
|
965
|
+
constructor(userActionId, message = "User action is no longer actionable") {
|
|
966
|
+
super(message);
|
|
967
|
+
__publicField(this, "userActionId");
|
|
968
|
+
this.name = "UserActionStaleError";
|
|
969
|
+
this.userActionId = userActionId;
|
|
970
|
+
}
|
|
971
|
+
};
|
|
1044
972
|
async function sendUserActionRequest(config, userActionId, action, data) {
|
|
1045
973
|
const url = buildUserActionUrl(config, userActionId, action);
|
|
1046
974
|
const baseHeaders = buildRequestHeaders(config);
|
|
@@ -1051,14 +979,17 @@ async function sendUserActionRequest(config, userActionId, action, data) {
|
|
|
1051
979
|
headers,
|
|
1052
980
|
body: hasBody ? JSON.stringify(data) : void 0
|
|
1053
981
|
});
|
|
982
|
+
if (response.status === 404) {
|
|
983
|
+
throw new UserActionStaleError(userActionId);
|
|
984
|
+
}
|
|
1054
985
|
if (!response.ok) {
|
|
1055
986
|
const errorText = await response.text();
|
|
1056
987
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1057
988
|
}
|
|
1058
989
|
return await response.json();
|
|
1059
990
|
}
|
|
1060
|
-
async function submitUserAction(config, userActionId,
|
|
1061
|
-
return sendUserActionRequest(config, userActionId, "submit",
|
|
991
|
+
async function submitUserAction(config, userActionId, content) {
|
|
992
|
+
return sendUserActionRequest(config, userActionId, "submit", content ?? {});
|
|
1062
993
|
}
|
|
1063
994
|
async function cancelUserAction(config, userActionId) {
|
|
1064
995
|
return sendUserActionRequest(config, userActionId, "cancel");
|
|
@@ -1140,6 +1071,13 @@ var activeStreamStore = {
|
|
|
1140
1071
|
streams.get(key)?.listeners.delete(listener);
|
|
1141
1072
|
};
|
|
1142
1073
|
},
|
|
1074
|
+
// Rename an entry — used when the server assigns a new session ID mid-stream
|
|
1075
|
+
rename(oldKey, newKey) {
|
|
1076
|
+
const entry = streams.get(oldKey);
|
|
1077
|
+
if (!entry) return;
|
|
1078
|
+
streams.set(newKey, entry);
|
|
1079
|
+
streams.delete(oldKey);
|
|
1080
|
+
},
|
|
1143
1081
|
// Explicit user cancel — aborts the controller and removes the entry
|
|
1144
1082
|
abort(key) {
|
|
1145
1083
|
const entry = streams.get(key);
|
|
@@ -1236,15 +1174,11 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1236
1174
|
onEvent: (event) => {
|
|
1237
1175
|
if (abortController.signal.aborted) return;
|
|
1238
1176
|
processStreamEventV2(event, state);
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
eventType,
|
|
1245
|
-
event.message?.trim() || event.errorMessage?.trim() || getEventMessage(event)
|
|
1246
|
-
);
|
|
1247
|
-
callbacksRef.current.onUserActionEvent?.(eventType, msg);
|
|
1177
|
+
if (state.lastUserAction) {
|
|
1178
|
+
callbacksRef.current.onUserActionRequired?.(state.lastUserAction);
|
|
1179
|
+
}
|
|
1180
|
+
if (state.lastNotification) {
|
|
1181
|
+
callbacksRef.current.onUserNotification?.(state.lastNotification);
|
|
1248
1182
|
}
|
|
1249
1183
|
const activeStep = state.steps.find((s) => s.id === state.currentExecutingStepId);
|
|
1250
1184
|
const lastInProgressStep = [...state.steps].reverse().find((s) => s.status === "in_progress");
|
|
@@ -1285,7 +1219,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1285
1219
|
currentExecutingStepId: state.currentExecutingStepId,
|
|
1286
1220
|
executionId: state.executionId,
|
|
1287
1221
|
sessionId: state.sessionId,
|
|
1288
|
-
userActionResult: state.userActionResult,
|
|
1289
1222
|
isCancelled: false
|
|
1290
1223
|
});
|
|
1291
1224
|
}
|
|
@@ -1296,14 +1229,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1296
1229
|
if (error.name !== "AbortError") {
|
|
1297
1230
|
callbacksRef.current.onError?.(error);
|
|
1298
1231
|
}
|
|
1299
|
-
if (state.userActionPending) {
|
|
1300
|
-
state.userActionPending = false;
|
|
1301
|
-
state.userActionRequest = void 0;
|
|
1302
|
-
callbacksRef.current.onUserActionEvent?.(
|
|
1303
|
-
"USER_ACTION_FAILED",
|
|
1304
|
-
"Connection lost. Please try again."
|
|
1305
|
-
);
|
|
1306
|
-
}
|
|
1307
1232
|
const isAborted = error.name === "AbortError";
|
|
1308
1233
|
setMessages(
|
|
1309
1234
|
(prev) => prev.map(
|
|
@@ -1332,14 +1257,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1332
1257
|
setIsWaitingForResponse(false);
|
|
1333
1258
|
callbacksRef.current.onStatusMessage?.(null);
|
|
1334
1259
|
callbacksRef.current.onStepsUpdate?.([]);
|
|
1335
|
-
if (state.userActionPending) {
|
|
1336
|
-
state.userActionPending = false;
|
|
1337
|
-
state.userActionRequest = void 0;
|
|
1338
|
-
callbacksRef.current.onUserActionEvent?.(
|
|
1339
|
-
"USER_ACTION_FAILED",
|
|
1340
|
-
"Verification could not be completed."
|
|
1341
|
-
);
|
|
1342
|
-
}
|
|
1343
1260
|
if (state.sessionId && state.sessionId !== sessionId) {
|
|
1344
1261
|
callbacksRef.current.onSessionIdChange?.(state.sessionId);
|
|
1345
1262
|
}
|
|
@@ -1363,7 +1280,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1363
1280
|
steps: state.hasError ? [] : [...state.steps],
|
|
1364
1281
|
isCancelled: false,
|
|
1365
1282
|
currentExecutingStepId: void 0,
|
|
1366
|
-
userActionResult: state.userActionResult,
|
|
1367
1283
|
formattedThinkingText: state.hasError ? void 0 : state.formattedThinkingText || void 0,
|
|
1368
1284
|
isResolvingImages: needsImageResolve,
|
|
1369
1285
|
totalElapsedMs: state.hasError ? void 0 : state.totalElapsedMs
|
|
@@ -1406,14 +1322,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1406
1322
|
if (error.name !== "AbortError") {
|
|
1407
1323
|
callbacksRef.current.onError?.(error);
|
|
1408
1324
|
}
|
|
1409
|
-
if (state.userActionPending) {
|
|
1410
|
-
state.userActionPending = false;
|
|
1411
|
-
state.userActionRequest = void 0;
|
|
1412
|
-
callbacksRef.current.onUserActionEvent?.(
|
|
1413
|
-
"USER_ACTION_FAILED",
|
|
1414
|
-
"Connection lost. Please try again."
|
|
1415
|
-
);
|
|
1416
|
-
}
|
|
1417
1325
|
const isAborted = error.name === "AbortError";
|
|
1418
1326
|
setMessages(
|
|
1419
1327
|
(prev) => prev.map(
|
|
@@ -1452,8 +1360,23 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1452
1360
|
}
|
|
1453
1361
|
|
|
1454
1362
|
// src/hooks/useChatV2.ts
|
|
1363
|
+
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1364
|
+
function upsertPrompt(prompts, req) {
|
|
1365
|
+
const active = { ...req, status: "pending" };
|
|
1366
|
+
const idx = prompts.findIndex(
|
|
1367
|
+
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
1368
|
+
);
|
|
1369
|
+
if (idx >= 0) {
|
|
1370
|
+
const next = prompts.slice();
|
|
1371
|
+
next[idx] = active;
|
|
1372
|
+
return next;
|
|
1373
|
+
}
|
|
1374
|
+
return [...prompts, active];
|
|
1375
|
+
}
|
|
1455
1376
|
function getStoredOrInitialMessages(config) {
|
|
1456
1377
|
if (!config.userId) return config.initialMessages ?? [];
|
|
1378
|
+
const activeStream = activeStreamStore.get(config.userId);
|
|
1379
|
+
if (activeStream) return activeStream.messages;
|
|
1457
1380
|
const stored = chatStore.get(config.userId);
|
|
1458
1381
|
if (stored.length > 0) return stored;
|
|
1459
1382
|
if (config.initialMessages?.length) {
|
|
@@ -1467,11 +1390,16 @@ function getSessionIdFromMessages(messages) {
|
|
|
1467
1390
|
}
|
|
1468
1391
|
function useChatV2(config, callbacks = {}) {
|
|
1469
1392
|
const [messages, setMessages] = react.useState(() => getStoredOrInitialMessages(config));
|
|
1470
|
-
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(
|
|
1393
|
+
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(() => {
|
|
1394
|
+
if (!config.userId) return false;
|
|
1395
|
+
return activeStreamStore.get(config.userId)?.isWaiting ?? false;
|
|
1396
|
+
});
|
|
1471
1397
|
const sessionIdRef = react.useRef(
|
|
1472
1398
|
getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
|
|
1473
1399
|
);
|
|
1474
1400
|
const prevUserIdRef = react.useRef(config.userId);
|
|
1401
|
+
const streamUserIdRef = react.useRef(void 0);
|
|
1402
|
+
const subscriptionPrevUserIdRef = react.useRef(config.userId);
|
|
1475
1403
|
const callbacksRef = react.useRef(callbacks);
|
|
1476
1404
|
callbacksRef.current = callbacks;
|
|
1477
1405
|
const configRef = react.useRef(config);
|
|
@@ -1480,33 +1408,35 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1480
1408
|
messagesRef.current = messages;
|
|
1481
1409
|
const storeAwareSetMessages = react.useCallback(
|
|
1482
1410
|
(updater) => {
|
|
1483
|
-
const
|
|
1484
|
-
|
|
1485
|
-
|
|
1411
|
+
const streamUserId = streamUserIdRef.current;
|
|
1412
|
+
const currentUserId = configRef.current.userId;
|
|
1413
|
+
const storeKey = streamUserId ?? currentUserId;
|
|
1414
|
+
if (storeKey && activeStreamStore.has(storeKey)) {
|
|
1415
|
+
activeStreamStore.applyMessages(storeKey, updater);
|
|
1416
|
+
}
|
|
1417
|
+
if (!streamUserId || streamUserId === currentUserId) {
|
|
1418
|
+
setMessages(updater);
|
|
1486
1419
|
}
|
|
1487
|
-
setMessages(updater);
|
|
1488
1420
|
},
|
|
1489
1421
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1490
1422
|
[]
|
|
1491
1423
|
);
|
|
1492
1424
|
const storeAwareSetIsWaiting = react.useCallback(
|
|
1493
1425
|
(waiting) => {
|
|
1494
|
-
const
|
|
1495
|
-
|
|
1496
|
-
|
|
1426
|
+
const streamUserId = streamUserIdRef.current;
|
|
1427
|
+
const currentUserId = configRef.current.userId;
|
|
1428
|
+
const storeKey = streamUserId ?? currentUserId;
|
|
1429
|
+
if (storeKey && activeStreamStore.has(storeKey)) {
|
|
1430
|
+
activeStreamStore.setWaiting(storeKey, waiting);
|
|
1431
|
+
}
|
|
1432
|
+
if (!streamUserId || streamUserId === currentUserId) {
|
|
1433
|
+
setIsWaitingForResponse(waiting);
|
|
1497
1434
|
}
|
|
1498
|
-
setIsWaitingForResponse(waiting);
|
|
1499
1435
|
},
|
|
1500
1436
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1501
1437
|
[]
|
|
1502
1438
|
);
|
|
1503
|
-
const [userActionState, setUserActionState] = react.useState(
|
|
1504
|
-
request: null,
|
|
1505
|
-
result: null,
|
|
1506
|
-
clearOtpTrigger: 0
|
|
1507
|
-
});
|
|
1508
|
-
const userActionStateRef = react.useRef(userActionState);
|
|
1509
|
-
userActionStateRef.current = userActionState;
|
|
1439
|
+
const [userActionState, setUserActionState] = react.useState(EMPTY_USER_ACTION_STATE);
|
|
1510
1440
|
const wrappedCallbacks = react.useMemo(() => ({
|
|
1511
1441
|
...callbacksRef.current,
|
|
1512
1442
|
onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
|
|
@@ -1516,26 +1446,17 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1516
1446
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1517
1447
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1518
1448
|
onUserActionRequired: (request) => {
|
|
1519
|
-
setUserActionState((prev) => ({
|
|
1449
|
+
setUserActionState((prev) => ({
|
|
1450
|
+
...prev,
|
|
1451
|
+
prompts: upsertPrompt(prev.prompts, request)
|
|
1452
|
+
}));
|
|
1520
1453
|
callbacksRef.current.onUserActionRequired?.(request);
|
|
1521
1454
|
},
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
case "USER_ACTION_REJECTED":
|
|
1528
|
-
setUserActionState((prev) => ({ ...prev, request: null, result: "rejected" }));
|
|
1529
|
-
break;
|
|
1530
|
-
case "USER_ACTION_EXPIRED":
|
|
1531
|
-
case "USER_ACTION_FAILED":
|
|
1532
|
-
setUserActionState((prev) => ({ ...prev, request: null }));
|
|
1533
|
-
break;
|
|
1534
|
-
case "USER_ACTION_INVALID":
|
|
1535
|
-
setUserActionState((prev) => ({ ...prev, clearOtpTrigger: prev.clearOtpTrigger + 1 }));
|
|
1536
|
-
break;
|
|
1537
|
-
}
|
|
1538
|
-
callbacksRef.current.onUserActionEvent?.(eventType, message);
|
|
1455
|
+
onUserNotification: (notification) => {
|
|
1456
|
+
setUserActionState(
|
|
1457
|
+
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1458
|
+
);
|
|
1459
|
+
callbacksRef.current.onUserNotification?.(notification);
|
|
1539
1460
|
}
|
|
1540
1461
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1541
1462
|
}), []);
|
|
@@ -1583,6 +1504,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1583
1504
|
const abortController = new AbortController();
|
|
1584
1505
|
const { userId } = configRef.current;
|
|
1585
1506
|
if (userId) {
|
|
1507
|
+
streamUserIdRef.current = userId;
|
|
1586
1508
|
const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
|
|
1587
1509
|
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1588
1510
|
}
|
|
@@ -1593,9 +1515,11 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1593
1515
|
abortController,
|
|
1594
1516
|
options
|
|
1595
1517
|
);
|
|
1596
|
-
|
|
1597
|
-
|
|
1518
|
+
const finalStreamUserId = streamUserIdRef.current ?? userId;
|
|
1519
|
+
if (finalStreamUserId) {
|
|
1520
|
+
activeStreamStore.complete(finalStreamUserId);
|
|
1598
1521
|
}
|
|
1522
|
+
streamUserIdRef.current = void 0;
|
|
1599
1523
|
if (!abortController.signal.aborted && newSessionId && newSessionId !== sessionIdRef.current) {
|
|
1600
1524
|
sessionIdRef.current = newSessionId;
|
|
1601
1525
|
}
|
|
@@ -1612,12 +1536,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1612
1536
|
setMessages((prev) => [...msgs, ...prev]);
|
|
1613
1537
|
}, []);
|
|
1614
1538
|
const cancelStream = react.useCallback(() => {
|
|
1615
|
-
|
|
1616
|
-
|
|
1539
|
+
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1540
|
+
if (streamUserId) {
|
|
1541
|
+
activeStreamStore.abort(streamUserId);
|
|
1617
1542
|
}
|
|
1543
|
+
streamUserIdRef.current = void 0;
|
|
1618
1544
|
cancelStreamManager();
|
|
1619
1545
|
setIsWaitingForResponse(false);
|
|
1620
|
-
setUserActionState((prev) => ({ ...prev,
|
|
1546
|
+
setUserActionState((prev) => ({ ...prev, prompts: [] }));
|
|
1621
1547
|
setMessages(
|
|
1622
1548
|
(prev) => prev.map((msg) => {
|
|
1623
1549
|
if (msg.isStreaming) {
|
|
@@ -1634,15 +1560,19 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1634
1560
|
);
|
|
1635
1561
|
}, [cancelStreamManager]);
|
|
1636
1562
|
const resetSession = react.useCallback(() => {
|
|
1563
|
+
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1564
|
+
if (streamUserId) {
|
|
1565
|
+
activeStreamStore.abort(streamUserId);
|
|
1566
|
+
}
|
|
1637
1567
|
if (configRef.current.userId) {
|
|
1638
|
-
activeStreamStore.abort(configRef.current.userId);
|
|
1639
1568
|
chatStore.delete(configRef.current.userId);
|
|
1640
1569
|
}
|
|
1570
|
+
streamUserIdRef.current = void 0;
|
|
1641
1571
|
setMessages([]);
|
|
1642
1572
|
sessionIdRef.current = void 0;
|
|
1643
1573
|
abortControllerRef.current?.abort();
|
|
1644
1574
|
setIsWaitingForResponse(false);
|
|
1645
|
-
setUserActionState(
|
|
1575
|
+
setUserActionState(EMPTY_USER_ACTION_STATE);
|
|
1646
1576
|
}, []);
|
|
1647
1577
|
const getSessionId = react.useCallback(() => {
|
|
1648
1578
|
return sessionIdRef.current;
|
|
@@ -1650,59 +1580,91 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1650
1580
|
const getMessages = react.useCallback(() => {
|
|
1651
1581
|
return messages;
|
|
1652
1582
|
}, [messages]);
|
|
1653
|
-
const
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1583
|
+
const setPromptStatus = react.useCallback(
|
|
1584
|
+
(userActionId, status) => {
|
|
1585
|
+
setUserActionState((prev) => ({
|
|
1586
|
+
...prev,
|
|
1587
|
+
prompts: prev.prompts.map(
|
|
1588
|
+
(p) => p.userActionId === userActionId ? { ...p, status } : p
|
|
1589
|
+
)
|
|
1590
|
+
}));
|
|
1591
|
+
},
|
|
1592
|
+
[]
|
|
1593
|
+
);
|
|
1594
|
+
const removePrompt = react.useCallback((userActionId) => {
|
|
1595
|
+
setUserActionState((prev) => ({
|
|
1596
|
+
...prev,
|
|
1597
|
+
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
1598
|
+
}));
|
|
1599
|
+
}, []);
|
|
1600
|
+
const submitUserAction2 = react.useCallback(
|
|
1601
|
+
async (userActionId, content) => {
|
|
1602
|
+
setPromptStatus(userActionId, "submitting");
|
|
1657
1603
|
try {
|
|
1658
|
-
await submitUserAction(configRef.current,
|
|
1604
|
+
await submitUserAction(configRef.current, userActionId, content);
|
|
1605
|
+
removePrompt(userActionId);
|
|
1659
1606
|
} catch (error) {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
}
|
|
1607
|
+
if (error instanceof UserActionStaleError) {
|
|
1608
|
+
setPromptStatus(userActionId, "stale");
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
setPromptStatus(userActionId, "pending");
|
|
1664
1612
|
callbacksRef.current.onError?.(error);
|
|
1665
1613
|
throw error;
|
|
1666
1614
|
}
|
|
1667
1615
|
},
|
|
1668
|
-
[]
|
|
1616
|
+
[removePrompt, setPromptStatus]
|
|
1669
1617
|
);
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
}
|
|
1618
|
+
const cancelUserAction2 = react.useCallback(
|
|
1619
|
+
async (userActionId) => {
|
|
1620
|
+
setPromptStatus(userActionId, "submitting");
|
|
1621
|
+
try {
|
|
1622
|
+
await cancelUserAction(configRef.current, userActionId);
|
|
1623
|
+
removePrompt(userActionId);
|
|
1624
|
+
} catch (error) {
|
|
1625
|
+
if (error instanceof UserActionStaleError) {
|
|
1626
|
+
removePrompt(userActionId);
|
|
1627
|
+
return;
|
|
1681
1628
|
}
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1629
|
+
setPromptStatus(userActionId, "pending");
|
|
1630
|
+
callbacksRef.current.onError?.(error);
|
|
1631
|
+
throw error;
|
|
1632
|
+
}
|
|
1633
|
+
},
|
|
1634
|
+
[removePrompt, setPromptStatus]
|
|
1635
|
+
);
|
|
1636
|
+
const resendUserAction2 = react.useCallback(
|
|
1637
|
+
async (userActionId) => {
|
|
1638
|
+
setPromptStatus(userActionId, "submitting");
|
|
1639
|
+
try {
|
|
1640
|
+
await resendUserAction(configRef.current, userActionId);
|
|
1641
|
+
setPromptStatus(userActionId, "pending");
|
|
1642
|
+
} catch (error) {
|
|
1643
|
+
if (error instanceof UserActionStaleError) {
|
|
1644
|
+
setPromptStatus(userActionId, "stale");
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
setPromptStatus(userActionId, "pending");
|
|
1648
|
+
callbacksRef.current.onError?.(error);
|
|
1649
|
+
throw error;
|
|
1650
|
+
}
|
|
1651
|
+
},
|
|
1652
|
+
[setPromptStatus]
|
|
1653
|
+
);
|
|
1654
|
+
const dismissNotification = react.useCallback((id) => {
|
|
1655
|
+
setUserActionState((prev) => ({
|
|
1656
|
+
...prev,
|
|
1657
|
+
notifications: prev.notifications.filter((n) => n.id !== id)
|
|
1658
|
+
}));
|
|
1702
1659
|
}, []);
|
|
1703
1660
|
react.useEffect(() => {
|
|
1661
|
+
const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
|
|
1662
|
+
subscriptionPrevUserIdRef.current = config.userId;
|
|
1704
1663
|
const { userId } = config;
|
|
1705
1664
|
if (!userId) return;
|
|
1665
|
+
if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
|
|
1666
|
+
streamUserIdRef.current = userId;
|
|
1667
|
+
}
|
|
1706
1668
|
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
|
|
1707
1669
|
setMessages(msgs);
|
|
1708
1670
|
setIsWaitingForResponse(isWaiting);
|
|
@@ -1716,6 +1678,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1716
1678
|
}, [config.userId]);
|
|
1717
1679
|
react.useEffect(() => {
|
|
1718
1680
|
if (!config.userId) return;
|
|
1681
|
+
if (prevUserIdRef.current !== config.userId) return;
|
|
1719
1682
|
const toSave = messages.filter((m) => !m.isStreaming);
|
|
1720
1683
|
if (toSave.length > 0) {
|
|
1721
1684
|
chatStore.set(config.userId, toSave);
|
|
@@ -1737,7 +1700,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1737
1700
|
setMessages([]);
|
|
1738
1701
|
sessionIdRef.current = void 0;
|
|
1739
1702
|
setIsWaitingForResponse(false);
|
|
1740
|
-
setUserActionState(
|
|
1703
|
+
setUserActionState(EMPTY_USER_ACTION_STATE);
|
|
1741
1704
|
} else if (config.userId) {
|
|
1742
1705
|
const active = activeStreamStore.get(config.userId);
|
|
1743
1706
|
if (active) {
|
|
@@ -1764,9 +1727,10 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1764
1727
|
isWaitingForResponse,
|
|
1765
1728
|
sessionId: sessionIdRef.current,
|
|
1766
1729
|
userActionState,
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1730
|
+
submitUserAction: submitUserAction2,
|
|
1731
|
+
cancelUserAction: cancelUserAction2,
|
|
1732
|
+
resendUserAction: resendUserAction2,
|
|
1733
|
+
dismissNotification
|
|
1770
1734
|
};
|
|
1771
1735
|
}
|
|
1772
1736
|
function useVoice() {
|
|
@@ -1885,15 +1849,151 @@ function useVoice() {
|
|
|
1885
1849
|
};
|
|
1886
1850
|
}
|
|
1887
1851
|
|
|
1852
|
+
// src/utils/jsonSchemaForm.ts
|
|
1853
|
+
function classifyField(field) {
|
|
1854
|
+
if (!field) return "text";
|
|
1855
|
+
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
1856
|
+
switch (field.type) {
|
|
1857
|
+
case "boolean":
|
|
1858
|
+
return "boolean";
|
|
1859
|
+
case "integer":
|
|
1860
|
+
return "integer";
|
|
1861
|
+
case "number":
|
|
1862
|
+
return "decimal";
|
|
1863
|
+
case "string":
|
|
1864
|
+
return "text";
|
|
1865
|
+
default:
|
|
1866
|
+
return "text";
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
function isNestedOrUnsupported(field) {
|
|
1870
|
+
if (!field) return false;
|
|
1871
|
+
if (field.type === "object" || field.type === "array") return true;
|
|
1872
|
+
if ("properties" in field && field.properties != null) return true;
|
|
1873
|
+
if ("items" in field && field.items != null) return true;
|
|
1874
|
+
return false;
|
|
1875
|
+
}
|
|
1876
|
+
function getOptions(field) {
|
|
1877
|
+
if (!field || !Array.isArray(field.oneOf)) return [];
|
|
1878
|
+
return field.oneOf.filter(
|
|
1879
|
+
(o) => !!o && typeof o === "object" && typeof o.const === "string"
|
|
1880
|
+
);
|
|
1881
|
+
}
|
|
1882
|
+
function isRequired(schema, key) {
|
|
1883
|
+
return Array.isArray(schema?.required) && schema.required.includes(key);
|
|
1884
|
+
}
|
|
1885
|
+
function coerceValue(field, raw) {
|
|
1886
|
+
const widget = classifyField(field);
|
|
1887
|
+
if (widget === "boolean") {
|
|
1888
|
+
if (typeof raw === "boolean") return raw;
|
|
1889
|
+
if (raw === "true") return true;
|
|
1890
|
+
if (raw === "false") return false;
|
|
1891
|
+
return Boolean(raw);
|
|
1892
|
+
}
|
|
1893
|
+
if (widget === "integer" || widget === "decimal") {
|
|
1894
|
+
if (raw === "" || raw == null) return void 0;
|
|
1895
|
+
const num = typeof raw === "number" ? raw : Number(String(raw).trim());
|
|
1896
|
+
if (Number.isNaN(num)) return void 0;
|
|
1897
|
+
return widget === "integer" ? Math.trunc(num) : num;
|
|
1898
|
+
}
|
|
1899
|
+
if (raw == null) return void 0;
|
|
1900
|
+
const str = String(raw);
|
|
1901
|
+
return str === "" ? void 0 : str;
|
|
1902
|
+
}
|
|
1903
|
+
function defaultValueFor(field) {
|
|
1904
|
+
if (!field || field.default === void 0) {
|
|
1905
|
+
return classifyField(field) === "boolean" ? false : "";
|
|
1906
|
+
}
|
|
1907
|
+
return field.default;
|
|
1908
|
+
}
|
|
1909
|
+
function validateField(field, value, required) {
|
|
1910
|
+
const widget = classifyField(field);
|
|
1911
|
+
const label = field?.title || "This field";
|
|
1912
|
+
const isEmpty = value === void 0 || value === null || typeof value === "string" && value.trim() === "";
|
|
1913
|
+
if (isEmpty) {
|
|
1914
|
+
if (required && widget !== "boolean") return `${label} is required.`;
|
|
1915
|
+
return null;
|
|
1916
|
+
}
|
|
1917
|
+
if (widget === "integer" || widget === "decimal") {
|
|
1918
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
1919
|
+
if (Number.isNaN(num)) return `${label} must be a number.`;
|
|
1920
|
+
if (widget === "integer" && !Number.isInteger(num)) {
|
|
1921
|
+
return `${label} must be a whole number.`;
|
|
1922
|
+
}
|
|
1923
|
+
if (typeof field?.minimum === "number" && num < field.minimum) {
|
|
1924
|
+
return `${label} must be at least ${field.minimum}.`;
|
|
1925
|
+
}
|
|
1926
|
+
if (typeof field?.maximum === "number" && num > field.maximum) {
|
|
1927
|
+
return `${label} must be at most ${field.maximum}.`;
|
|
1928
|
+
}
|
|
1929
|
+
return null;
|
|
1930
|
+
}
|
|
1931
|
+
if (widget === "select") {
|
|
1932
|
+
const allowed = getOptions(field).map((o) => o.const);
|
|
1933
|
+
if (allowed.length > 0 && !allowed.includes(String(value))) {
|
|
1934
|
+
return `${label} has an invalid selection.`;
|
|
1935
|
+
}
|
|
1936
|
+
return null;
|
|
1937
|
+
}
|
|
1938
|
+
const str = String(value);
|
|
1939
|
+
if (typeof field?.minLength === "number" && str.length < field.minLength) {
|
|
1940
|
+
return `${label} must be at least ${field.minLength} characters.`;
|
|
1941
|
+
}
|
|
1942
|
+
if (typeof field?.maxLength === "number" && str.length > field.maxLength) {
|
|
1943
|
+
return `${label} must be at most ${field.maxLength} characters.`;
|
|
1944
|
+
}
|
|
1945
|
+
return null;
|
|
1946
|
+
}
|
|
1947
|
+
function renderableFields(schema) {
|
|
1948
|
+
const props = schema?.properties;
|
|
1949
|
+
if (!props) return [];
|
|
1950
|
+
return Object.entries(props).filter(([, field]) => !isNestedOrUnsupported(field));
|
|
1951
|
+
}
|
|
1952
|
+
function validateForm(schema, values) {
|
|
1953
|
+
const errors = {};
|
|
1954
|
+
for (const [key, field] of renderableFields(schema)) {
|
|
1955
|
+
const coerced = coerceValue(field, values[key]);
|
|
1956
|
+
const err = validateField(field, coerced, isRequired(schema, key));
|
|
1957
|
+
if (err) errors[key] = err;
|
|
1958
|
+
}
|
|
1959
|
+
return errors;
|
|
1960
|
+
}
|
|
1961
|
+
function buildContent(schema, values) {
|
|
1962
|
+
const content = {};
|
|
1963
|
+
for (const [key, field] of renderableFields(schema)) {
|
|
1964
|
+
const coerced = coerceValue(field, values[key]);
|
|
1965
|
+
if (coerced !== void 0) content[key] = coerced;
|
|
1966
|
+
}
|
|
1967
|
+
return content;
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
// src/index.ts
|
|
1971
|
+
function migrateActiveStream(oldUserId, newUserId) {
|
|
1972
|
+
activeStreamStore.rename(oldUserId, newUserId);
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
exports.UserActionStaleError = UserActionStaleError;
|
|
1976
|
+
exports.buildContent = buildContent;
|
|
1888
1977
|
exports.buildFormattedThinking = buildFormattedThinking;
|
|
1889
1978
|
exports.cancelUserAction = cancelUserAction;
|
|
1979
|
+
exports.classifyField = classifyField;
|
|
1980
|
+
exports.classifyUserActionKind = classifyUserActionKind;
|
|
1981
|
+
exports.coerceValue = coerceValue;
|
|
1890
1982
|
exports.createInitialV2State = createInitialV2State;
|
|
1983
|
+
exports.defaultValueFor = defaultValueFor;
|
|
1891
1984
|
exports.generateId = generateId;
|
|
1985
|
+
exports.getOptions = getOptions;
|
|
1986
|
+
exports.isNestedOrUnsupported = isNestedOrUnsupported;
|
|
1987
|
+
exports.isRequired = isRequired;
|
|
1988
|
+
exports.migrateActiveStream = migrateActiveStream;
|
|
1892
1989
|
exports.processStreamEventV2 = processStreamEventV2;
|
|
1990
|
+
exports.renderableFields = renderableFields;
|
|
1893
1991
|
exports.resendUserAction = resendUserAction;
|
|
1894
1992
|
exports.streamWorkflowEvents = streamWorkflowEvents;
|
|
1895
1993
|
exports.submitUserAction = submitUserAction;
|
|
1896
1994
|
exports.useChatV2 = useChatV2;
|
|
1897
1995
|
exports.useVoice = useVoice;
|
|
1996
|
+
exports.validateField = validateField;
|
|
1997
|
+
exports.validateForm = validateForm;
|
|
1898
1998
|
//# sourceMappingURL=index.native.js.map
|
|
1899
1999
|
//# sourceMappingURL=index.native.js.map
|