@paymanai/payman-ask-sdk 4.0.25 → 4.0.27
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 +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1380 -331
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1121 -72
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +65 -6
- package/dist/index.native.js.map +1 -1
- package/dist/styles.css +131 -0
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var framerMotion = require('framer-motion');
|
|
5
5
|
var clsx = require('clsx');
|
|
6
6
|
var tailwindMerge = require('tailwind-merge');
|
|
@@ -33,6 +33,7 @@ function _interopNamespace(e) {
|
|
|
33
33
|
return Object.freeze(n);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
36
37
|
var Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
|
|
37
38
|
var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
38
39
|
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
@@ -300,6 +301,8 @@ function getEventMessage(event) {
|
|
|
300
301
|
}
|
|
301
302
|
case "RUN_IN_PROGRESS":
|
|
302
303
|
return event.partialText || "Thinking...";
|
|
304
|
+
case "LLM_CALL_STARTED":
|
|
305
|
+
return event.description || "";
|
|
303
306
|
case "RUN_COMPLETED":
|
|
304
307
|
return "Agent run completed";
|
|
305
308
|
case "RUN_FAILED":
|
|
@@ -437,7 +440,8 @@ function createInitialV2State() {
|
|
|
437
440
|
finalData: void 0,
|
|
438
441
|
steps: [],
|
|
439
442
|
stepCounter: 0,
|
|
440
|
-
currentExecutingStepId: void 0
|
|
443
|
+
currentExecutingStepId: void 0,
|
|
444
|
+
trailingActivity: false
|
|
441
445
|
};
|
|
442
446
|
}
|
|
443
447
|
function upsertUserAction(state, req) {
|
|
@@ -459,6 +463,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
459
463
|
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
460
464
|
if (event.executionId) state.executionId = event.executionId;
|
|
461
465
|
if (event.sessionId) state.sessionId = event.sessionId;
|
|
466
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
462
467
|
const description = typeof event.description === "string" ? event.description : "";
|
|
463
468
|
if (description) {
|
|
464
469
|
for (let i = state.steps.length - 1; i >= 0; i--) {
|
|
@@ -493,7 +498,12 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
493
498
|
state.lastEventType = eventType;
|
|
494
499
|
break;
|
|
495
500
|
}
|
|
501
|
+
case "LLM_CALL_STARTED":
|
|
502
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
503
|
+
state.lastEventType = eventType;
|
|
504
|
+
break;
|
|
496
505
|
case "INTENT_STARTED": {
|
|
506
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
497
507
|
const stepId = `step-${state.stepCounter++}`;
|
|
498
508
|
state.steps.push({
|
|
499
509
|
id: stepId,
|
|
@@ -509,6 +519,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
509
519
|
break;
|
|
510
520
|
}
|
|
511
521
|
case "INTENT_COMPLETED": {
|
|
522
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
512
523
|
const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
|
|
513
524
|
if (intentStep) {
|
|
514
525
|
intentStep.status = "completed";
|
|
@@ -540,6 +551,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
540
551
|
step2.status = "completed";
|
|
541
552
|
}
|
|
542
553
|
});
|
|
554
|
+
state.trailingActivity = false;
|
|
543
555
|
state.lastEventType = eventType;
|
|
544
556
|
break;
|
|
545
557
|
}
|
|
@@ -611,6 +623,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
611
623
|
case "WORKFLOW_ERROR":
|
|
612
624
|
state.hasError = true;
|
|
613
625
|
state.errorMessage = event.errorMessage || event.message || "Workflow error";
|
|
626
|
+
state.trailingActivity = false;
|
|
614
627
|
state.lastEventType = eventType;
|
|
615
628
|
break;
|
|
616
629
|
// ---- K2 pipeline stage lifecycle events ----
|
|
@@ -853,12 +866,12 @@ async function resolveRagImageUrls(config, content, signal) {
|
|
|
853
866
|
}
|
|
854
867
|
var FRIENDLY_ERROR_MESSAGE = "Oops, something went wrong. Please try again.";
|
|
855
868
|
function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForResponse) {
|
|
856
|
-
const abortControllerRef =
|
|
857
|
-
const configRef =
|
|
869
|
+
const abortControllerRef = React.useRef(null);
|
|
870
|
+
const configRef = React.useRef(config);
|
|
858
871
|
configRef.current = config;
|
|
859
|
-
const callbacksRef =
|
|
872
|
+
const callbacksRef = React.useRef(callbacks);
|
|
860
873
|
callbacksRef.current = callbacks;
|
|
861
|
-
const startStream =
|
|
874
|
+
const startStream = React.useCallback(
|
|
862
875
|
async (userMessage, streamingId, sessionId, externalAbortController, options) => {
|
|
863
876
|
abortControllerRef.current?.abort();
|
|
864
877
|
const abortController = externalAbortController ?? new AbortController();
|
|
@@ -899,7 +912,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
899
912
|
const latestUsefulStep = [...state.steps].reverse().find(
|
|
900
913
|
(s) => s.message && !isBlandStatus(s.message)
|
|
901
914
|
);
|
|
902
|
-
const
|
|
915
|
+
const eventTypeUpper = typeof event.eventType === "string" ? event.eventType.toUpperCase() : "";
|
|
916
|
+
const liveEventLabel = eventTypeUpper === "KEEP_ALIVE" || eventTypeUpper === "LLM_CALL_STARTED" ? useful(getEventMessage(event)) : void 0;
|
|
917
|
+
const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? liveEventLabel ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
|
|
903
918
|
// nothing useful seen yet). Render the bland label so the
|
|
904
919
|
// bubble isn't blank.
|
|
905
920
|
activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
|
|
@@ -924,6 +939,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
924
939
|
streamingContent: state.finalResponse,
|
|
925
940
|
content: "",
|
|
926
941
|
currentMessage,
|
|
942
|
+
hasTrailingActivity: state.trailingActivity,
|
|
927
943
|
streamProgress: "processing",
|
|
928
944
|
isError: false,
|
|
929
945
|
steps: [...state.steps],
|
|
@@ -1057,7 +1073,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1057
1073
|
},
|
|
1058
1074
|
[setMessages, setIsWaitingForResponse]
|
|
1059
1075
|
);
|
|
1060
|
-
const cancelStream =
|
|
1076
|
+
const cancelStream = React.useCallback(() => {
|
|
1061
1077
|
abortControllerRef.current?.abort();
|
|
1062
1078
|
}, []);
|
|
1063
1079
|
return {
|
|
@@ -1139,6 +1155,9 @@ function getUserActionSecondsLeft(prompt) {
|
|
|
1139
1155
|
return void 0;
|
|
1140
1156
|
}
|
|
1141
1157
|
var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
|
|
1158
|
+
function promptSlotKey(p) {
|
|
1159
|
+
return p.toolCallId || p.userActionId;
|
|
1160
|
+
}
|
|
1142
1161
|
function upsertPrompt(prompts, req) {
|
|
1143
1162
|
const idx = prompts.findIndex(
|
|
1144
1163
|
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
@@ -1168,24 +1187,25 @@ function getSessionIdFromMessages(messages) {
|
|
|
1168
1187
|
return messages.find((message) => message.sessionId)?.sessionId;
|
|
1169
1188
|
}
|
|
1170
1189
|
function useChatV2(config, callbacks = {}) {
|
|
1171
|
-
const [messages, setMessages] =
|
|
1172
|
-
const [isWaitingForResponse, setIsWaitingForResponse] =
|
|
1190
|
+
const [messages, setMessages] = React.useState(() => getStoredOrInitialMessages(config));
|
|
1191
|
+
const [isWaitingForResponse, setIsWaitingForResponse] = React.useState(() => {
|
|
1173
1192
|
if (!config.userId) return false;
|
|
1174
1193
|
return activeStreamStore.get(config.userId)?.isWaiting ?? false;
|
|
1175
1194
|
});
|
|
1176
|
-
const sessionIdRef =
|
|
1195
|
+
const sessionIdRef = React.useRef(
|
|
1177
1196
|
getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
|
|
1178
1197
|
);
|
|
1179
|
-
const prevUserIdRef =
|
|
1180
|
-
const streamUserIdRef =
|
|
1181
|
-
const subscriptionPrevUserIdRef =
|
|
1182
|
-
const callbacksRef =
|
|
1198
|
+
const prevUserIdRef = React.useRef(config.userId);
|
|
1199
|
+
const streamUserIdRef = React.useRef(void 0);
|
|
1200
|
+
const subscriptionPrevUserIdRef = React.useRef(config.userId);
|
|
1201
|
+
const callbacksRef = React.useRef(callbacks);
|
|
1183
1202
|
callbacksRef.current = callbacks;
|
|
1184
|
-
const configRef =
|
|
1203
|
+
const configRef = React.useRef(config);
|
|
1185
1204
|
configRef.current = config;
|
|
1186
|
-
const messagesRef =
|
|
1205
|
+
const messagesRef = React.useRef(messages);
|
|
1187
1206
|
messagesRef.current = messages;
|
|
1188
|
-
const
|
|
1207
|
+
const pendingSubmissionsRef = React.useRef(/* @__PURE__ */ new Map());
|
|
1208
|
+
const storeAwareSetMessages = React.useCallback(
|
|
1189
1209
|
(updater) => {
|
|
1190
1210
|
const streamUserId = streamUserIdRef.current;
|
|
1191
1211
|
const currentUserId = configRef.current.userId;
|
|
@@ -1200,7 +1220,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1200
1220
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1201
1221
|
[]
|
|
1202
1222
|
);
|
|
1203
|
-
const storeAwareSetIsWaiting =
|
|
1223
|
+
const storeAwareSetIsWaiting = React.useCallback(
|
|
1204
1224
|
(waiting) => {
|
|
1205
1225
|
const streamUserId = streamUserIdRef.current;
|
|
1206
1226
|
const currentUserId = configRef.current.userId;
|
|
@@ -1215,11 +1235,13 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1215
1235
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1216
1236
|
[]
|
|
1217
1237
|
);
|
|
1218
|
-
const [userActionState, setUserActionState] =
|
|
1238
|
+
const [userActionState, setUserActionState] = React.useState(() => {
|
|
1219
1239
|
if (!config.userId) return EMPTY_USER_ACTION_STATE2;
|
|
1220
1240
|
return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
|
|
1221
1241
|
});
|
|
1222
|
-
const
|
|
1242
|
+
const userActionStateRef = React.useRef(userActionState);
|
|
1243
|
+
userActionStateRef.current = userActionState;
|
|
1244
|
+
const storeAwareSetUserActionState = React.useCallback(
|
|
1223
1245
|
(updater) => {
|
|
1224
1246
|
const streamUserId = streamUserIdRef.current;
|
|
1225
1247
|
const currentUserId = configRef.current.userId;
|
|
@@ -1237,7 +1259,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1237
1259
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1238
1260
|
[]
|
|
1239
1261
|
);
|
|
1240
|
-
const wrappedCallbacks =
|
|
1262
|
+
const wrappedCallbacks = React.useMemo(() => ({
|
|
1241
1263
|
...callbacksRef.current,
|
|
1242
1264
|
onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
|
|
1243
1265
|
onStreamStart: () => callbacksRef.current.onStreamStart?.(),
|
|
@@ -1246,6 +1268,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1246
1268
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1247
1269
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1248
1270
|
onUserActionRequired: (request) => {
|
|
1271
|
+
const requestSlotKey = promptSlotKey(request);
|
|
1272
|
+
for (const [pendingId, slotKey] of pendingSubmissionsRef.current) {
|
|
1273
|
+
if (slotKey === requestSlotKey) {
|
|
1274
|
+
pendingSubmissionsRef.current.delete(pendingId);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1249
1277
|
storeAwareSetUserActionState((prev) => ({
|
|
1250
1278
|
...prev,
|
|
1251
1279
|
prompts: upsertPrompt(prev.prompts, request)
|
|
@@ -1257,6 +1285,28 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1257
1285
|
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1258
1286
|
);
|
|
1259
1287
|
callbacksRef.current.onUserNotification?.(notification);
|
|
1288
|
+
},
|
|
1289
|
+
// A submitted-but-unconfirmed prompt (see `submitUserAction`) is only
|
|
1290
|
+
// safe to drop once the stream has demonstrably moved on. `onEvent`
|
|
1291
|
+
// in useStreamManagerV2 calls `onStepsUpdate` for *every* processed
|
|
1292
|
+
// stream event, unconditionally — so the first time this fires
|
|
1293
|
+
// after a submission, the event in hand is either the rejection
|
|
1294
|
+
// retry (a fresh `USER_ACTION_REQUIRED`, which the handler above
|
|
1295
|
+
// already deleted this pending entry for, earlier in the very same
|
|
1296
|
+
// event) or genuine forward progress (RUN_IN_PROGRESS, a tool call,
|
|
1297
|
+
// content deltas, RUN_COMPLETED, ...). Anything still pending by
|
|
1298
|
+
// the time we get here therefore means the run resumed normally —
|
|
1299
|
+
// clear it.
|
|
1300
|
+
onStepsUpdate: (steps) => {
|
|
1301
|
+
if (pendingSubmissionsRef.current.size > 0) {
|
|
1302
|
+
const resolved = [...pendingSubmissionsRef.current.keys()];
|
|
1303
|
+
pendingSubmissionsRef.current.clear();
|
|
1304
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1305
|
+
...prev,
|
|
1306
|
+
prompts: prev.prompts.filter((p) => !resolved.includes(p.userActionId))
|
|
1307
|
+
}));
|
|
1308
|
+
}
|
|
1309
|
+
callbacksRef.current.onStepsUpdate?.(steps);
|
|
1260
1310
|
}
|
|
1261
1311
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1262
1312
|
}), []);
|
|
@@ -1266,7 +1316,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1266
1316
|
storeAwareSetMessages,
|
|
1267
1317
|
storeAwareSetIsWaiting
|
|
1268
1318
|
);
|
|
1269
|
-
const sendMessage =
|
|
1319
|
+
const sendMessage = React.useCallback(
|
|
1270
1320
|
async (userMessage, options) => {
|
|
1271
1321
|
if (!userMessage.trim()) return;
|
|
1272
1322
|
if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
|
|
@@ -1326,16 +1376,16 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1326
1376
|
},
|
|
1327
1377
|
[startStream]
|
|
1328
1378
|
);
|
|
1329
|
-
const clearMessages =
|
|
1379
|
+
const clearMessages = React.useCallback(() => {
|
|
1330
1380
|
if (configRef.current.userId) {
|
|
1331
1381
|
chatStore.delete(configRef.current.userId);
|
|
1332
1382
|
}
|
|
1333
1383
|
setMessages([]);
|
|
1334
1384
|
}, []);
|
|
1335
|
-
const prependMessages =
|
|
1385
|
+
const prependMessages = React.useCallback((msgs) => {
|
|
1336
1386
|
setMessages((prev) => [...msgs, ...prev]);
|
|
1337
1387
|
}, []);
|
|
1338
|
-
const cancelStream =
|
|
1388
|
+
const cancelStream = React.useCallback(() => {
|
|
1339
1389
|
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1340
1390
|
if (streamUserId) {
|
|
1341
1391
|
activeStreamStore.abort(streamUserId);
|
|
@@ -1359,7 +1409,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1359
1409
|
})
|
|
1360
1410
|
);
|
|
1361
1411
|
}, [cancelStreamManager, storeAwareSetUserActionState]);
|
|
1362
|
-
const resetSession =
|
|
1412
|
+
const resetSession = React.useCallback(() => {
|
|
1363
1413
|
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1364
1414
|
if (streamUserId) {
|
|
1365
1415
|
activeStreamStore.abort(streamUserId);
|
|
@@ -1374,13 +1424,13 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1374
1424
|
setIsWaitingForResponse(false);
|
|
1375
1425
|
storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
|
|
1376
1426
|
}, []);
|
|
1377
|
-
const getSessionId =
|
|
1427
|
+
const getSessionId = React.useCallback(() => {
|
|
1378
1428
|
return sessionIdRef.current;
|
|
1379
1429
|
}, []);
|
|
1380
|
-
const getMessages =
|
|
1430
|
+
const getMessages = React.useCallback(() => {
|
|
1381
1431
|
return messages;
|
|
1382
1432
|
}, [messages]);
|
|
1383
|
-
const setPromptStatus =
|
|
1433
|
+
const setPromptStatus = React.useCallback(
|
|
1384
1434
|
(userActionId, status) => {
|
|
1385
1435
|
storeAwareSetUserActionState((prev) => ({
|
|
1386
1436
|
...prev,
|
|
@@ -1391,18 +1441,22 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1391
1441
|
},
|
|
1392
1442
|
[storeAwareSetUserActionState]
|
|
1393
1443
|
);
|
|
1394
|
-
const removePrompt =
|
|
1444
|
+
const removePrompt = React.useCallback((userActionId) => {
|
|
1445
|
+
pendingSubmissionsRef.current.delete(userActionId);
|
|
1395
1446
|
storeAwareSetUserActionState((prev) => ({
|
|
1396
1447
|
...prev,
|
|
1397
1448
|
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
1398
1449
|
}));
|
|
1399
1450
|
}, [storeAwareSetUserActionState]);
|
|
1400
|
-
const submitUserAction2 =
|
|
1451
|
+
const submitUserAction2 = React.useCallback(
|
|
1401
1452
|
async (userActionId, content) => {
|
|
1402
1453
|
setPromptStatus(userActionId, "submitting");
|
|
1403
1454
|
try {
|
|
1404
1455
|
await submitUserAction(configRef.current, userActionId, content);
|
|
1405
|
-
|
|
1456
|
+
const prompt = userActionStateRef.current.prompts.find(
|
|
1457
|
+
(p) => p.userActionId === userActionId
|
|
1458
|
+
);
|
|
1459
|
+
pendingSubmissionsRef.current.set(userActionId, prompt ? promptSlotKey(prompt) : userActionId);
|
|
1406
1460
|
} catch (error) {
|
|
1407
1461
|
if (error instanceof UserActionStaleError) {
|
|
1408
1462
|
setPromptStatus(userActionId, "stale");
|
|
@@ -1413,9 +1467,9 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1413
1467
|
throw error;
|
|
1414
1468
|
}
|
|
1415
1469
|
},
|
|
1416
|
-
[
|
|
1470
|
+
[setPromptStatus]
|
|
1417
1471
|
);
|
|
1418
|
-
const cancelUserAction2 =
|
|
1472
|
+
const cancelUserAction2 = React.useCallback(
|
|
1419
1473
|
async (userActionId) => {
|
|
1420
1474
|
setPromptStatus(userActionId, "submitting");
|
|
1421
1475
|
try {
|
|
@@ -1433,7 +1487,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1433
1487
|
},
|
|
1434
1488
|
[removePrompt, setPromptStatus]
|
|
1435
1489
|
);
|
|
1436
|
-
const resendUserAction2 =
|
|
1490
|
+
const resendUserAction2 = React.useCallback(
|
|
1437
1491
|
async (userActionId) => {
|
|
1438
1492
|
setPromptStatus(userActionId, "submitting");
|
|
1439
1493
|
try {
|
|
@@ -1451,7 +1505,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1451
1505
|
},
|
|
1452
1506
|
[setPromptStatus]
|
|
1453
1507
|
);
|
|
1454
|
-
const expireUserAction2 =
|
|
1508
|
+
const expireUserAction2 = React.useCallback(
|
|
1455
1509
|
async (userActionId) => {
|
|
1456
1510
|
setPromptStatus(userActionId, "expired");
|
|
1457
1511
|
try {
|
|
@@ -1464,13 +1518,13 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1464
1518
|
},
|
|
1465
1519
|
[setPromptStatus]
|
|
1466
1520
|
);
|
|
1467
|
-
const dismissNotification =
|
|
1521
|
+
const dismissNotification = React.useCallback((id) => {
|
|
1468
1522
|
storeAwareSetUserActionState((prev) => ({
|
|
1469
1523
|
...prev,
|
|
1470
1524
|
notifications: prev.notifications.filter((n) => n.id !== id)
|
|
1471
1525
|
}));
|
|
1472
1526
|
}, [storeAwareSetUserActionState]);
|
|
1473
|
-
|
|
1527
|
+
React.useEffect(() => {
|
|
1474
1528
|
const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
|
|
1475
1529
|
subscriptionPrevUserIdRef.current = config.userId;
|
|
1476
1530
|
const { userId } = config;
|
|
@@ -1492,7 +1546,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1492
1546
|
}
|
|
1493
1547
|
return unsubscribe;
|
|
1494
1548
|
}, [config.userId]);
|
|
1495
|
-
|
|
1549
|
+
React.useEffect(() => {
|
|
1496
1550
|
if (!config.userId) return;
|
|
1497
1551
|
if (prevUserIdRef.current !== config.userId) return;
|
|
1498
1552
|
const toSave = messages.filter((m) => !m.isStreaming);
|
|
@@ -1500,14 +1554,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1500
1554
|
chatStore.set(config.userId, toSave);
|
|
1501
1555
|
}
|
|
1502
1556
|
}, [messages, config.userId]);
|
|
1503
|
-
|
|
1557
|
+
React.useEffect(() => {
|
|
1504
1558
|
if (!config.userId || activeStreamStore.has(config.userId)) return;
|
|
1505
1559
|
if (!config.initialMessages?.length || messagesRef.current.length > 0) return;
|
|
1506
1560
|
chatStore.set(config.userId, config.initialMessages);
|
|
1507
1561
|
setMessages(config.initialMessages);
|
|
1508
1562
|
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
|
|
1509
1563
|
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1510
|
-
|
|
1564
|
+
React.useEffect(() => {
|
|
1511
1565
|
const prevUserId = prevUserIdRef.current;
|
|
1512
1566
|
prevUserIdRef.current = config.userId;
|
|
1513
1567
|
if (prevUserId === config.userId) return;
|
|
@@ -1557,12 +1611,12 @@ function getSpeechRecognition() {
|
|
|
1557
1611
|
return window.SpeechRecognition || window.webkitSpeechRecognition || null;
|
|
1558
1612
|
}
|
|
1559
1613
|
function useVoice(config = {}, callbacks = {}) {
|
|
1560
|
-
const [voiceState, setVoiceState] =
|
|
1561
|
-
const [transcribedText, setTranscribedText] =
|
|
1562
|
-
const [isAvailable, setIsAvailable] =
|
|
1563
|
-
const [isRecording, setIsRecording] =
|
|
1564
|
-
const recognitionRef =
|
|
1565
|
-
const autoStopTimerRef =
|
|
1614
|
+
const [voiceState, setVoiceState] = React.useState("idle");
|
|
1615
|
+
const [transcribedText, setTranscribedText] = React.useState("");
|
|
1616
|
+
const [isAvailable, setIsAvailable] = React.useState(false);
|
|
1617
|
+
const [isRecording, setIsRecording] = React.useState(false);
|
|
1618
|
+
const recognitionRef = React.useRef(null);
|
|
1619
|
+
const autoStopTimerRef = React.useRef(null);
|
|
1566
1620
|
const {
|
|
1567
1621
|
lang = "en-US",
|
|
1568
1622
|
interimResults = true,
|
|
@@ -1571,14 +1625,14 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1571
1625
|
autoStopAfterSilence
|
|
1572
1626
|
} = config;
|
|
1573
1627
|
const { onStart, onEnd, onResult, onError, onStateChange } = callbacks;
|
|
1574
|
-
|
|
1628
|
+
React.useEffect(() => {
|
|
1575
1629
|
const SpeechRecognitionAPI = getSpeechRecognition();
|
|
1576
1630
|
setIsAvailable(SpeechRecognitionAPI !== null);
|
|
1577
1631
|
}, []);
|
|
1578
|
-
|
|
1632
|
+
React.useEffect(() => {
|
|
1579
1633
|
onStateChange?.(voiceState);
|
|
1580
1634
|
}, [voiceState, onStateChange]);
|
|
1581
|
-
const requestPermissions =
|
|
1635
|
+
const requestPermissions = React.useCallback(async () => {
|
|
1582
1636
|
try {
|
|
1583
1637
|
const result = await navigator.mediaDevices.getUserMedia({
|
|
1584
1638
|
audio: true
|
|
@@ -1595,7 +1649,7 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1595
1649
|
};
|
|
1596
1650
|
}
|
|
1597
1651
|
}, []);
|
|
1598
|
-
const getPermissions =
|
|
1652
|
+
const getPermissions = React.useCallback(async () => {
|
|
1599
1653
|
if (typeof navigator === "undefined" || !navigator.permissions) {
|
|
1600
1654
|
return {
|
|
1601
1655
|
granted: false,
|
|
@@ -1617,13 +1671,13 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1617
1671
|
};
|
|
1618
1672
|
}
|
|
1619
1673
|
}, []);
|
|
1620
|
-
const clearAutoStopTimer =
|
|
1674
|
+
const clearAutoStopTimer = React.useCallback(() => {
|
|
1621
1675
|
if (autoStopTimerRef.current) {
|
|
1622
1676
|
clearTimeout(autoStopTimerRef.current);
|
|
1623
1677
|
autoStopTimerRef.current = null;
|
|
1624
1678
|
}
|
|
1625
1679
|
}, []);
|
|
1626
|
-
const resetAutoStopTimer =
|
|
1680
|
+
const resetAutoStopTimer = React.useCallback(() => {
|
|
1627
1681
|
clearAutoStopTimer();
|
|
1628
1682
|
if (autoStopAfterSilence && autoStopAfterSilence > 0) {
|
|
1629
1683
|
autoStopTimerRef.current = setTimeout(() => {
|
|
@@ -1633,7 +1687,7 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1633
1687
|
}, autoStopAfterSilence);
|
|
1634
1688
|
}
|
|
1635
1689
|
}, [autoStopAfterSilence, clearAutoStopTimer, isRecording]);
|
|
1636
|
-
const stopRecording =
|
|
1690
|
+
const stopRecording = React.useCallback(() => {
|
|
1637
1691
|
if (recognitionRef.current) {
|
|
1638
1692
|
try {
|
|
1639
1693
|
recognitionRef.current.stop();
|
|
@@ -1645,7 +1699,7 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1645
1699
|
setIsRecording(false);
|
|
1646
1700
|
setVoiceState("idle");
|
|
1647
1701
|
}, [clearAutoStopTimer]);
|
|
1648
|
-
const startRecording =
|
|
1702
|
+
const startRecording = React.useCallback(async () => {
|
|
1649
1703
|
const SpeechRecognitionAPI = getSpeechRecognition();
|
|
1650
1704
|
if (!SpeechRecognitionAPI) {
|
|
1651
1705
|
onError?.("Speech recognition not supported in this browser");
|
|
@@ -1735,15 +1789,15 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1735
1789
|
resetAutoStopTimer,
|
|
1736
1790
|
clearAutoStopTimer
|
|
1737
1791
|
]);
|
|
1738
|
-
const clearTranscript =
|
|
1792
|
+
const clearTranscript = React.useCallback(() => {
|
|
1739
1793
|
setTranscribedText("");
|
|
1740
1794
|
}, []);
|
|
1741
|
-
const reset =
|
|
1795
|
+
const reset = React.useCallback(() => {
|
|
1742
1796
|
stopRecording();
|
|
1743
1797
|
setTranscribedText("");
|
|
1744
1798
|
setVoiceState("idle");
|
|
1745
1799
|
}, [stopRecording]);
|
|
1746
|
-
|
|
1800
|
+
React.useEffect(() => {
|
|
1747
1801
|
return () => {
|
|
1748
1802
|
if (recognitionRef.current) {
|
|
1749
1803
|
try {
|
|
@@ -1883,9 +1937,9 @@ function buildContent(schema, values) {
|
|
|
1883
1937
|
}
|
|
1884
1938
|
return content;
|
|
1885
1939
|
}
|
|
1886
|
-
var PaymanChatContext =
|
|
1940
|
+
var PaymanChatContext = React.createContext(void 0);
|
|
1887
1941
|
function usePaymanChat() {
|
|
1888
|
-
const context =
|
|
1942
|
+
const context = React.useContext(PaymanChatContext);
|
|
1889
1943
|
if (!context) {
|
|
1890
1944
|
throw new Error("usePaymanChat must be used within a PaymanChat component");
|
|
1891
1945
|
}
|
|
@@ -2082,6 +2136,9 @@ function getConflictErrorMessage(errorDetails) {
|
|
|
2082
2136
|
}
|
|
2083
2137
|
function initSentryIfNeeded(dsn) {
|
|
2084
2138
|
if (!dsn) return;
|
|
2139
|
+
if (typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")) {
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2085
2142
|
if (Sentry__namespace.getClient()) return;
|
|
2086
2143
|
Sentry__namespace.init({
|
|
2087
2144
|
dsn,
|
|
@@ -2143,8 +2200,8 @@ function ImageLightbox({
|
|
|
2143
2200
|
alt = "",
|
|
2144
2201
|
onClose
|
|
2145
2202
|
}) {
|
|
2146
|
-
const [isMounted, setIsMounted] =
|
|
2147
|
-
const [isImageLoaded, setIsImageLoaded] =
|
|
2203
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
2204
|
+
const [isImageLoaded, setIsImageLoaded] = React.useState(false);
|
|
2148
2205
|
const overlayStyle = {
|
|
2149
2206
|
position: "fixed",
|
|
2150
2207
|
inset: 0,
|
|
@@ -2165,14 +2222,14 @@ function ImageLightbox({
|
|
|
2165
2222
|
justifyContent: "center",
|
|
2166
2223
|
overflow: "hidden"
|
|
2167
2224
|
};
|
|
2168
|
-
|
|
2225
|
+
React.useEffect(() => {
|
|
2169
2226
|
setIsMounted(true);
|
|
2170
2227
|
return () => setIsMounted(false);
|
|
2171
2228
|
}, []);
|
|
2172
|
-
|
|
2229
|
+
React.useEffect(() => {
|
|
2173
2230
|
setIsImageLoaded(false);
|
|
2174
2231
|
}, [src]);
|
|
2175
|
-
|
|
2232
|
+
React.useEffect(() => {
|
|
2176
2233
|
if (typeof document === "undefined") return;
|
|
2177
2234
|
const previousOverflow = document.body.style.overflow;
|
|
2178
2235
|
document.body.style.overflow = "hidden";
|
|
@@ -2180,7 +2237,7 @@ function ImageLightbox({
|
|
|
2180
2237
|
document.body.style.overflow = previousOverflow;
|
|
2181
2238
|
};
|
|
2182
2239
|
}, []);
|
|
2183
|
-
|
|
2240
|
+
React.useEffect(() => {
|
|
2184
2241
|
if (typeof document === "undefined") return;
|
|
2185
2242
|
const handleKeyDown = (event) => {
|
|
2186
2243
|
if (event.key === "Escape") {
|
|
@@ -2276,15 +2333,15 @@ function MarkdownImage({
|
|
|
2276
2333
|
maxHeight: "18rem",
|
|
2277
2334
|
objectFit: "contain"
|
|
2278
2335
|
};
|
|
2279
|
-
const [isLoaded, setIsLoaded] =
|
|
2280
|
-
const [hasError, setHasError] =
|
|
2281
|
-
const [isLightboxOpen, setIsLightboxOpen] =
|
|
2282
|
-
const isUnresolvedRagImage =
|
|
2336
|
+
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
2337
|
+
const [hasError, setHasError] = React.useState(false);
|
|
2338
|
+
const [isLightboxOpen, setIsLightboxOpen] = React.useState(false);
|
|
2339
|
+
const isUnresolvedRagImage = React.useMemo(
|
|
2283
2340
|
() => src ? isUnresolvedRagImageSource(src) : false,
|
|
2284
2341
|
[src]
|
|
2285
2342
|
);
|
|
2286
2343
|
const isResolvingRagImage = isResolving && isUnresolvedRagImage;
|
|
2287
|
-
|
|
2344
|
+
React.useEffect(() => {
|
|
2288
2345
|
setIsLoaded(false);
|
|
2289
2346
|
setHasError(false);
|
|
2290
2347
|
setIsLightboxOpen(false);
|
|
@@ -2411,9 +2468,9 @@ function AgentMessage({
|
|
|
2411
2468
|
const hasTraceData = !!(message.tracingData || message.executionId) && !isStreaming;
|
|
2412
2469
|
const isCancelled = message.isCancelled ?? false;
|
|
2413
2470
|
const currentExecutingStepId = message.currentExecutingStepId;
|
|
2414
|
-
const [isStepsExpanded, setIsStepsExpanded] =
|
|
2415
|
-
const wasStreamingRef =
|
|
2416
|
-
|
|
2471
|
+
const [isStepsExpanded, setIsStepsExpanded] = React.useState(false);
|
|
2472
|
+
const wasStreamingRef = React.useRef(isStreaming);
|
|
2473
|
+
React.useEffect(() => {
|
|
2417
2474
|
if (isStreaming && hasSteps) {
|
|
2418
2475
|
setIsStepsExpanded(true);
|
|
2419
2476
|
}
|
|
@@ -2430,13 +2487,13 @@ function AgentMessage({
|
|
|
2430
2487
|
const completedWithNoContent = !isStreaming && !isCancelled && content.length === 0 && (message.streamProgress === "completed" || message.streamProgress === "error");
|
|
2431
2488
|
const conflictErrorMessage = getConflictErrorMessage(message.errorDetails);
|
|
2432
2489
|
const isError = !!conflictErrorMessage || (isFriendlyWorkflowError(message.errorDetails) || looksLikeRawError(content)) && !hasMeaningfulContent || completedWithNoContent;
|
|
2433
|
-
const currentStep =
|
|
2490
|
+
const currentStep = React.useMemo(
|
|
2434
2491
|
() => message.steps?.find(
|
|
2435
2492
|
(s) => s.id === currentExecutingStepId && s.status === "in_progress"
|
|
2436
2493
|
),
|
|
2437
2494
|
[message.steps, currentExecutingStepId]
|
|
2438
2495
|
);
|
|
2439
|
-
const markdownRenderers =
|
|
2496
|
+
const markdownRenderers = React.useMemo(
|
|
2440
2497
|
() => createMarkdownComponents({
|
|
2441
2498
|
isResolvingImages: message.isResolvingImages
|
|
2442
2499
|
}),
|
|
@@ -2510,8 +2567,8 @@ function AgentMessage({
|
|
|
2510
2567
|
}) })
|
|
2511
2568
|
}
|
|
2512
2569
|
) });
|
|
2513
|
-
const stepsToggleRef =
|
|
2514
|
-
const handleStepsToggle =
|
|
2570
|
+
const stepsToggleRef = React.useRef(null);
|
|
2571
|
+
const handleStepsToggle = React.useCallback(() => {
|
|
2515
2572
|
setIsStepsExpanded((prev) => {
|
|
2516
2573
|
const next = !prev;
|
|
2517
2574
|
if (next) {
|
|
@@ -2839,23 +2896,23 @@ function MessageList({
|
|
|
2839
2896
|
isLoadingMoreMessages = false,
|
|
2840
2897
|
hasMoreMessages = false
|
|
2841
2898
|
}) {
|
|
2842
|
-
const scrollRef =
|
|
2843
|
-
const isNearBottomRef =
|
|
2844
|
-
const [showScrollBtn, setShowScrollBtn] =
|
|
2845
|
-
const prevMessageCountRef =
|
|
2846
|
-
const scrollHeightBeforePrependRef =
|
|
2847
|
-
const firstMessageIdRef =
|
|
2848
|
-
const getDistanceFromBottom =
|
|
2899
|
+
const scrollRef = React.useRef(null);
|
|
2900
|
+
const isNearBottomRef = React.useRef(true);
|
|
2901
|
+
const [showScrollBtn, setShowScrollBtn] = React.useState(false);
|
|
2902
|
+
const prevMessageCountRef = React.useRef(messages.length);
|
|
2903
|
+
const scrollHeightBeforePrependRef = React.useRef(null);
|
|
2904
|
+
const firstMessageIdRef = React.useRef(messages[0]?.id);
|
|
2905
|
+
const getDistanceFromBottom = React.useCallback(() => {
|
|
2849
2906
|
const el = scrollRef.current;
|
|
2850
2907
|
if (!el) return 0;
|
|
2851
2908
|
return el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
2852
2909
|
}, []);
|
|
2853
|
-
const scrollToBottom =
|
|
2910
|
+
const scrollToBottom = React.useCallback((behavior = "smooth") => {
|
|
2854
2911
|
const el = scrollRef.current;
|
|
2855
2912
|
if (!el) return;
|
|
2856
2913
|
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
2857
2914
|
}, []);
|
|
2858
|
-
const handleScroll =
|
|
2915
|
+
const handleScroll = React.useCallback(() => {
|
|
2859
2916
|
const el = scrollRef.current;
|
|
2860
2917
|
if (!el) return;
|
|
2861
2918
|
const distance = getDistanceFromBottom();
|
|
@@ -2867,7 +2924,7 @@ function MessageList({
|
|
|
2867
2924
|
onLoadMoreMessages();
|
|
2868
2925
|
}
|
|
2869
2926
|
}, [getDistanceFromBottom, hasMoreMessages, isLoadingMoreMessages, onLoadMoreMessages]);
|
|
2870
|
-
|
|
2927
|
+
React.useLayoutEffect(() => {
|
|
2871
2928
|
const el = scrollRef.current;
|
|
2872
2929
|
const prevHeight = scrollHeightBeforePrependRef.current;
|
|
2873
2930
|
const newFirstId = messages[0]?.id;
|
|
@@ -2877,25 +2934,25 @@ function MessageList({
|
|
|
2877
2934
|
}
|
|
2878
2935
|
firstMessageIdRef.current = newFirstId;
|
|
2879
2936
|
}, [messages]);
|
|
2880
|
-
|
|
2937
|
+
React.useEffect(() => {
|
|
2881
2938
|
const prevCount = prevMessageCountRef.current;
|
|
2882
2939
|
prevMessageCountRef.current = messages.length;
|
|
2883
2940
|
if (messages.length > prevCount && isNearBottomRef.current) {
|
|
2884
2941
|
requestAnimationFrame(() => scrollToBottom());
|
|
2885
2942
|
}
|
|
2886
2943
|
}, [messages.length, scrollToBottom]);
|
|
2887
|
-
|
|
2944
|
+
React.useEffect(() => {
|
|
2888
2945
|
const lastMsg = messages[messages.length - 1];
|
|
2889
2946
|
if (!lastMsg?.isStreaming) return;
|
|
2890
2947
|
if (!isNearBottomRef.current) return;
|
|
2891
2948
|
requestAnimationFrame(() => scrollToBottom());
|
|
2892
2949
|
});
|
|
2893
|
-
|
|
2950
|
+
React.useEffect(() => {
|
|
2894
2951
|
if (messages.length > 0) {
|
|
2895
2952
|
setTimeout(() => scrollToBottom("instant"), 50);
|
|
2896
2953
|
}
|
|
2897
2954
|
}, []);
|
|
2898
|
-
|
|
2955
|
+
React.useEffect(() => {
|
|
2899
2956
|
const handleStepsToggle = () => {
|
|
2900
2957
|
requestAnimationFrame(() => {
|
|
2901
2958
|
requestAnimationFrame(() => {
|
|
@@ -2912,7 +2969,7 @@ function MessageList({
|
|
|
2912
2969
|
return () => el.removeEventListener("payman-steps-toggle", handleStepsToggle);
|
|
2913
2970
|
}
|
|
2914
2971
|
}, [getDistanceFromBottom, scrollToBottom]);
|
|
2915
|
-
const handleScrollToBottom =
|
|
2972
|
+
const handleScrollToBottom = React.useCallback(() => {
|
|
2916
2973
|
scrollToBottom();
|
|
2917
2974
|
}, [scrollToBottom]);
|
|
2918
2975
|
if (isLoading) {
|
|
@@ -3045,7 +3102,7 @@ function ResetSessionConfirmModal({
|
|
|
3045
3102
|
onClose,
|
|
3046
3103
|
onConfirm
|
|
3047
3104
|
}) {
|
|
3048
|
-
const handleKeyDown =
|
|
3105
|
+
const handleKeyDown = React.useCallback(
|
|
3049
3106
|
(event) => {
|
|
3050
3107
|
if (event.key === "Escape") {
|
|
3051
3108
|
onClose();
|
|
@@ -3053,7 +3110,7 @@ function ResetSessionConfirmModal({
|
|
|
3053
3110
|
},
|
|
3054
3111
|
[onClose]
|
|
3055
3112
|
);
|
|
3056
|
-
|
|
3113
|
+
React.useEffect(() => {
|
|
3057
3114
|
if (!isOpen || typeof document === "undefined") return;
|
|
3058
3115
|
document.addEventListener("keydown", handleKeyDown);
|
|
3059
3116
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -3159,14 +3216,14 @@ function UserMessageV2({
|
|
|
3159
3216
|
retryDisabled = false,
|
|
3160
3217
|
actions
|
|
3161
3218
|
}) {
|
|
3162
|
-
const [copied, setCopied] =
|
|
3163
|
-
const [toast, setToast] =
|
|
3164
|
-
const copyResetTimerRef =
|
|
3165
|
-
const toastTimerRef =
|
|
3219
|
+
const [copied, setCopied] = React.useState(false);
|
|
3220
|
+
const [toast, setToast] = React.useState(null);
|
|
3221
|
+
const copyResetTimerRef = React.useRef(null);
|
|
3222
|
+
const toastTimerRef = React.useRef(null);
|
|
3166
3223
|
const showCopyAction = actions?.copy ?? true;
|
|
3167
3224
|
const showEditAction = actions?.edit ?? false;
|
|
3168
3225
|
const showRetryAction = actions?.retry ?? false;
|
|
3169
|
-
|
|
3226
|
+
React.useEffect(() => {
|
|
3170
3227
|
return () => {
|
|
3171
3228
|
if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
|
|
3172
3229
|
if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
|
|
@@ -3322,18 +3379,18 @@ function MarkdownImageV2({
|
|
|
3322
3379
|
onImageClick
|
|
3323
3380
|
}) {
|
|
3324
3381
|
const cachedAlready = src ? loadedImageCache.has(src) : false;
|
|
3325
|
-
const [isVisible, setIsVisible] =
|
|
3326
|
-
const [isLoaded, setIsLoaded] =
|
|
3327
|
-
const [hasError, setHasError] =
|
|
3328
|
-
const [retryCount, setRetryCount] =
|
|
3329
|
-
const sentinelRef =
|
|
3330
|
-
const prevLoadedRef =
|
|
3331
|
-
const isUnresolvedRag =
|
|
3382
|
+
const [isVisible, setIsVisible] = React.useState(cachedAlready);
|
|
3383
|
+
const [isLoaded, setIsLoaded] = React.useState(cachedAlready);
|
|
3384
|
+
const [hasError, setHasError] = React.useState(false);
|
|
3385
|
+
const [retryCount, setRetryCount] = React.useState(0);
|
|
3386
|
+
const sentinelRef = React.useRef(null);
|
|
3387
|
+
const prevLoadedRef = React.useRef(cachedAlready);
|
|
3388
|
+
const isUnresolvedRag = React.useMemo(
|
|
3332
3389
|
() => src ? isUnresolvedRagImageSource2(src) : false,
|
|
3333
3390
|
[src]
|
|
3334
3391
|
);
|
|
3335
3392
|
const isResolvingRag = Boolean(isResolving && isUnresolvedRag);
|
|
3336
|
-
|
|
3393
|
+
React.useEffect(() => {
|
|
3337
3394
|
if (src && loadedImageCache.has(src)) {
|
|
3338
3395
|
setIsLoaded(true);
|
|
3339
3396
|
setIsVisible(true);
|
|
@@ -3342,7 +3399,7 @@ function MarkdownImageV2({
|
|
|
3342
3399
|
setHasError(false);
|
|
3343
3400
|
setRetryCount(0);
|
|
3344
3401
|
}, [src]);
|
|
3345
|
-
|
|
3402
|
+
React.useEffect(() => {
|
|
3346
3403
|
const el = sentinelRef.current;
|
|
3347
3404
|
if (!el || !src) return;
|
|
3348
3405
|
const rect = el.getBoundingClientRect();
|
|
@@ -3463,9 +3520,88 @@ function MarkdownImageV2({
|
|
|
3463
3520
|
}
|
|
3464
3521
|
) });
|
|
3465
3522
|
}
|
|
3466
|
-
|
|
3523
|
+
var RAG_SOURCE_CLASS = "payman-v2-rag-source";
|
|
3524
|
+
var RAG_FOLLOW_UP_CLASS = "payman-v2-rag-follow-up";
|
|
3525
|
+
var SOURCE_PATTERN = /^Sources?:\s*\S/i;
|
|
3526
|
+
var MAX_FOLLOW_UP_LENGTH = 320;
|
|
3527
|
+
var HR_PATTERN = /^-{3,}$|^_{3,}$|^\*{3,}$/;
|
|
3528
|
+
function normalizeRagParagraphText(text) {
|
|
3529
|
+
return text.replace(/\s+/g, " ").trim();
|
|
3530
|
+
}
|
|
3531
|
+
function isRagSourceParagraph(text) {
|
|
3532
|
+
return SOURCE_PATTERN.test(normalizeRagParagraphText(text));
|
|
3533
|
+
}
|
|
3534
|
+
function isRagFollowUpCandidate(text) {
|
|
3535
|
+
const normalized = normalizeRagParagraphText(text);
|
|
3536
|
+
return normalized.length > 0 && normalized.length <= MAX_FOLLOW_UP_LENGTH && normalized.endsWith("?");
|
|
3537
|
+
}
|
|
3538
|
+
function extractRagParagraphTexts(content) {
|
|
3539
|
+
const paragraphs = [];
|
|
3540
|
+
const currentParagraph = [];
|
|
3541
|
+
const flushParagraph = () => {
|
|
3542
|
+
const paragraph = normalizeRagParagraphText(currentParagraph.join(" "));
|
|
3543
|
+
currentParagraph.length = 0;
|
|
3544
|
+
if (paragraph) paragraphs.push(paragraph);
|
|
3545
|
+
};
|
|
3546
|
+
content.replace(/\\n/g, "\n").split(/\r?\n/).forEach((line) => {
|
|
3547
|
+
const trimmedLine = line.trim();
|
|
3548
|
+
if (!trimmedLine) {
|
|
3549
|
+
flushParagraph();
|
|
3550
|
+
return;
|
|
3551
|
+
}
|
|
3552
|
+
if (HR_PATTERN.test(trimmedLine)) {
|
|
3553
|
+
flushParagraph();
|
|
3554
|
+
return;
|
|
3555
|
+
}
|
|
3556
|
+
currentParagraph.push(trimmedLine);
|
|
3557
|
+
});
|
|
3558
|
+
flushParagraph();
|
|
3559
|
+
return paragraphs;
|
|
3560
|
+
}
|
|
3561
|
+
function getRagAnswerParagraphRoles(paragraphs) {
|
|
3562
|
+
const normalized = paragraphs.map(normalizeRagParagraphText);
|
|
3563
|
+
const roles = normalized.map(() => null);
|
|
3564
|
+
const sourceIndexes = normalized.map((paragraph, index) => isRagSourceParagraph(paragraph) ? index : -1).filter((index) => index >= 0);
|
|
3565
|
+
for (const sourceIndex of sourceIndexes) {
|
|
3566
|
+
roles[sourceIndex] = "source";
|
|
3567
|
+
for (const candidateIndex of [sourceIndex - 1, sourceIndex + 1]) {
|
|
3568
|
+
if (candidateIndex >= 0 && candidateIndex < normalized.length && roles[candidateIndex] == null && isRagFollowUpCandidate(normalized[candidateIndex] ?? "")) {
|
|
3569
|
+
roles[candidateIndex] = "follow-up";
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
return roles;
|
|
3574
|
+
}
|
|
3575
|
+
function getRagAnswerParagraphRole(paragraph, paragraphs) {
|
|
3576
|
+
const normalizedParagraph = normalizeRagParagraphText(paragraph);
|
|
3577
|
+
if (isRagSourceParagraph(normalizedParagraph)) return "source";
|
|
3578
|
+
const roles = getRagAnswerParagraphRoles(paragraphs);
|
|
3579
|
+
return paragraphs.map(normalizeRagParagraphText).some((candidate, index) => {
|
|
3580
|
+
return candidate === normalizedParagraph && roles[index] === "follow-up";
|
|
3581
|
+
}) ? "follow-up" : null;
|
|
3582
|
+
}
|
|
3583
|
+
function ragAnswerRoleClassName(role) {
|
|
3584
|
+
if (role === "source") return RAG_SOURCE_CLASS;
|
|
3585
|
+
if (role === "follow-up") return RAG_FOLLOW_UP_CLASS;
|
|
3586
|
+
return void 0;
|
|
3587
|
+
}
|
|
3588
|
+
function reactNodeText(node) {
|
|
3589
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
3590
|
+
if (Array.isArray(node)) return node.map(reactNodeText).join("");
|
|
3591
|
+
if (React__namespace.isValidElement(node)) {
|
|
3592
|
+
return reactNodeText(node.props.children);
|
|
3593
|
+
}
|
|
3594
|
+
return "";
|
|
3595
|
+
}
|
|
3596
|
+
function buildComponents(onImageClick, isResolvingRef, ragParagraphsRef) {
|
|
3467
3597
|
return {
|
|
3468
|
-
p: ({ children }) =>
|
|
3598
|
+
p: ({ children }) => {
|
|
3599
|
+
const role = getRagAnswerParagraphRole(
|
|
3600
|
+
reactNodeText(children),
|
|
3601
|
+
ragParagraphsRef?.current ?? []
|
|
3602
|
+
);
|
|
3603
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: ragAnswerRoleClassName(role), children });
|
|
3604
|
+
},
|
|
3469
3605
|
code: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("code", { children }),
|
|
3470
3606
|
pre: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { children }) }),
|
|
3471
3607
|
ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { children }),
|
|
@@ -3501,10 +3637,15 @@ function MarkdownRendererV2({
|
|
|
3501
3637
|
isResolvingImages,
|
|
3502
3638
|
onImageClick
|
|
3503
3639
|
}) {
|
|
3504
|
-
const isResolvingRef =
|
|
3640
|
+
const isResolvingRef = React.useRef(isResolvingImages);
|
|
3505
3641
|
isResolvingRef.current = isResolvingImages;
|
|
3506
|
-
const
|
|
3507
|
-
|
|
3642
|
+
const ragParagraphsRef = React.useRef([]);
|
|
3643
|
+
ragParagraphsRef.current = React.useMemo(
|
|
3644
|
+
() => extractRagParagraphTexts(content),
|
|
3645
|
+
[content]
|
|
3646
|
+
);
|
|
3647
|
+
const components = React.useMemo(
|
|
3648
|
+
() => buildComponents(onImageClick, isResolvingRef, ragParagraphsRef),
|
|
3508
3649
|
[onImageClick]
|
|
3509
3650
|
);
|
|
3510
3651
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3561,14 +3702,14 @@ function FeedbackReasonModal({
|
|
|
3561
3702
|
onClose,
|
|
3562
3703
|
onSubmit
|
|
3563
3704
|
}) {
|
|
3564
|
-
const [reason, setReason] =
|
|
3705
|
+
const [reason, setReason] = React.useState(
|
|
3565
3706
|
NEGATIVE_FEEDBACK_REASONS[0].value
|
|
3566
3707
|
);
|
|
3567
|
-
const [details, setDetails] =
|
|
3568
|
-
const [submitting, setSubmitting] =
|
|
3569
|
-
const [error, setError] =
|
|
3570
|
-
const [reasonOpen, setReasonOpen] =
|
|
3571
|
-
|
|
3708
|
+
const [details, setDetails] = React.useState("");
|
|
3709
|
+
const [submitting, setSubmitting] = React.useState(false);
|
|
3710
|
+
const [error, setError] = React.useState(null);
|
|
3711
|
+
const [reasonOpen, setReasonOpen] = React.useState(false);
|
|
3712
|
+
React.useEffect(() => {
|
|
3572
3713
|
if (open) {
|
|
3573
3714
|
setReason(NEGATIVE_FEEDBACK_REASONS[0].value);
|
|
3574
3715
|
setDetails("");
|
|
@@ -3577,7 +3718,7 @@ function FeedbackReasonModal({
|
|
|
3577
3718
|
setReasonOpen(false);
|
|
3578
3719
|
}
|
|
3579
3720
|
}, [open]);
|
|
3580
|
-
const handleKeyDown =
|
|
3721
|
+
const handleKeyDown = React.useCallback(
|
|
3581
3722
|
(event) => {
|
|
3582
3723
|
if (event.key !== "Escape") return;
|
|
3583
3724
|
if (reasonOpen) {
|
|
@@ -3588,7 +3729,7 @@ function FeedbackReasonModal({
|
|
|
3588
3729
|
},
|
|
3589
3730
|
[onClose, reasonOpen]
|
|
3590
3731
|
);
|
|
3591
|
-
|
|
3732
|
+
React.useEffect(() => {
|
|
3592
3733
|
if (!open || typeof document === "undefined") return;
|
|
3593
3734
|
document.addEventListener("keydown", handleKeyDown);
|
|
3594
3735
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -3872,17 +4013,17 @@ function charDelay(char, speed, multiplier) {
|
|
|
3872
4013
|
function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText, speedMultiplier = 1) {
|
|
3873
4014
|
const instant = speedMultiplier === 0;
|
|
3874
4015
|
const multiplier = instant ? 1 : Math.max(speedMultiplier, 0.1);
|
|
3875
|
-
const [displayedText, setDisplayedText] =
|
|
3876
|
-
const displayedRef =
|
|
3877
|
-
const targetRef =
|
|
3878
|
-
const enabledRef =
|
|
3879
|
-
const initialDisplayedRef =
|
|
3880
|
-
const timerRef =
|
|
3881
|
-
const runningRef =
|
|
4016
|
+
const [displayedText, setDisplayedText] = React.useState("");
|
|
4017
|
+
const displayedRef = React.useRef("");
|
|
4018
|
+
const targetRef = React.useRef(targetText);
|
|
4019
|
+
const enabledRef = React.useRef(enabled);
|
|
4020
|
+
const initialDisplayedRef = React.useRef(initialDisplayedText);
|
|
4021
|
+
const timerRef = React.useRef(null);
|
|
4022
|
+
const runningRef = React.useRef(false);
|
|
3882
4023
|
targetRef.current = targetText;
|
|
3883
4024
|
enabledRef.current = enabled;
|
|
3884
4025
|
initialDisplayedRef.current = initialDisplayedText;
|
|
3885
|
-
|
|
4026
|
+
React.useEffect(() => {
|
|
3886
4027
|
if (!enabled || instant) {
|
|
3887
4028
|
if (timerRef.current) {
|
|
3888
4029
|
clearTimeout(timerRef.current);
|
|
@@ -3965,26 +4106,26 @@ function AssistantMessageV2({
|
|
|
3965
4106
|
actions,
|
|
3966
4107
|
typingSpeed = 4
|
|
3967
4108
|
}) {
|
|
3968
|
-
const [copied, setCopied] =
|
|
3969
|
-
const [activeFeedback, setActiveFeedback] =
|
|
4109
|
+
const [copied, setCopied] = React.useState(false);
|
|
4110
|
+
const [activeFeedback, setActiveFeedback] = React.useState(
|
|
3970
4111
|
() => getFeedbackState(message)
|
|
3971
4112
|
);
|
|
3972
|
-
const [reasonModalOpen, setReasonModalOpen] =
|
|
4113
|
+
const [reasonModalOpen, setReasonModalOpen] = React.useState(false);
|
|
3973
4114
|
const canSubmitFeedback = !!onSubmitFeedback && !!message.executionId;
|
|
3974
|
-
const [toast, setToast] =
|
|
3975
|
-
const copyResetTimerRef =
|
|
3976
|
-
const toastTimerRef =
|
|
4115
|
+
const [toast, setToast] = React.useState(null);
|
|
4116
|
+
const copyResetTimerRef = React.useRef(null);
|
|
4117
|
+
const toastTimerRef = React.useRef(null);
|
|
3977
4118
|
const showCopyAction = actions?.copy ?? true;
|
|
3978
4119
|
const showTraceAction = (actions?.trace ?? true) && !!onExecutionTraceClick;
|
|
3979
4120
|
const showThumbsUp = actions?.thumbsUp ?? true;
|
|
3980
4121
|
const showThumbsDown = actions?.thumbsDown ?? true;
|
|
3981
4122
|
const hydratedFeedback = message.feedback;
|
|
3982
|
-
const hasEverStreamed =
|
|
4123
|
+
const hasEverStreamed = React.useRef(!!message.isStreaming);
|
|
3983
4124
|
if (message.isStreaming) hasEverStreamed.current = true;
|
|
3984
|
-
|
|
4125
|
+
React.useEffect(() => {
|
|
3985
4126
|
setActiveFeedback(getFeedbackState(message));
|
|
3986
4127
|
}, [hydratedFeedback, message.id]);
|
|
3987
|
-
|
|
4128
|
+
React.useEffect(() => {
|
|
3988
4129
|
return () => {
|
|
3989
4130
|
if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
|
|
3990
4131
|
if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
|
|
@@ -3997,6 +4138,7 @@ function AssistantMessageV2({
|
|
|
3997
4138
|
return message.isStreaming ? stripIncompleteImageToken(normalized) : normalized;
|
|
3998
4139
|
})();
|
|
3999
4140
|
const isThinkingStreaming = !!message.isStreaming && !rawResponseContent && !message.isError;
|
|
4141
|
+
const showTrailingProgress = !!message.isStreaming && !!rawResponseContent && !message.isError && !message.isCancelled && !!message.hasTrailingActivity;
|
|
4000
4142
|
const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
|
|
4001
4143
|
const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(
|
|
4002
4144
|
rawResponseContent,
|
|
@@ -4005,6 +4147,8 @@ function AssistantMessageV2({
|
|
|
4005
4147
|
void 0,
|
|
4006
4148
|
typingSpeed
|
|
4007
4149
|
);
|
|
4150
|
+
const displayContentPending = Boolean(rawResponseContent) && !displayContent;
|
|
4151
|
+
const showThinkingBlock = isThinkingStreaming || displayContentPending;
|
|
4008
4152
|
const stickyLabel = (() => {
|
|
4009
4153
|
const steps = message.steps;
|
|
4010
4154
|
if (!steps || steps.length === 0) return void 0;
|
|
@@ -4139,7 +4283,7 @@ function AssistantMessageV2({
|
|
|
4139
4283
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4140
4284
|
toastPortal,
|
|
4141
4285
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: [
|
|
4142
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children:
|
|
4286
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showThinkingBlock && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4143
4287
|
framerMotion.motion.div,
|
|
4144
4288
|
{
|
|
4145
4289
|
initial: { opacity: 0, height: 0 },
|
|
@@ -4155,7 +4299,7 @@ function AssistantMessageV2({
|
|
|
4155
4299
|
{
|
|
4156
4300
|
isStreaming: isThinkingStreaming,
|
|
4157
4301
|
stickyLabel,
|
|
4158
|
-
currentStepLabel
|
|
4302
|
+
currentStepLabel: currentStepLabel ?? message.currentMessage
|
|
4159
4303
|
}
|
|
4160
4304
|
)
|
|
4161
4305
|
},
|
|
@@ -4169,7 +4313,32 @@ function AssistantMessageV2({
|
|
|
4169
4313
|
isResolvingImages: message.isResolvingImages,
|
|
4170
4314
|
onImageClick
|
|
4171
4315
|
}
|
|
4316
|
+
) : displayContentPending ? (
|
|
4317
|
+
// The intent/status line above is still bridging this
|
|
4318
|
+
// gap (see `showThinkingBlock`) — nothing to add here.
|
|
4319
|
+
null
|
|
4172
4320
|
) : !isThinkingStreaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
|
|
4321
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showTrailingProgress && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4322
|
+
framerMotion.motion.div,
|
|
4323
|
+
{
|
|
4324
|
+
initial: { opacity: 0, height: 0 },
|
|
4325
|
+
animate: { opacity: 1, height: "auto" },
|
|
4326
|
+
exit: { opacity: 0, height: 0 },
|
|
4327
|
+
transition: {
|
|
4328
|
+
duration: 0.32,
|
|
4329
|
+
ease: [0.2, 0, 0, 1]
|
|
4330
|
+
},
|
|
4331
|
+
style: { overflow: "hidden" },
|
|
4332
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4333
|
+
ThinkingBlockV2,
|
|
4334
|
+
{
|
|
4335
|
+
isStreaming: true,
|
|
4336
|
+
currentStepLabel: message.currentMessage ?? currentStepLabel
|
|
4337
|
+
}
|
|
4338
|
+
)
|
|
4339
|
+
},
|
|
4340
|
+
"trailing-progress"
|
|
4341
|
+
) }),
|
|
4173
4342
|
isCancelled && message.isStreaming && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-assistant-msg-paused", children: [
|
|
4174
4343
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4175
4344
|
lucideReact.WifiOff,
|
|
@@ -4268,6 +4437,112 @@ function AssistantMessageV2({
|
|
|
4268
4437
|
)
|
|
4269
4438
|
] });
|
|
4270
4439
|
}
|
|
4440
|
+
var CHAR_VARIANTS = {
|
|
4441
|
+
fade: {
|
|
4442
|
+
initial: { opacity: 0, scale: 0.7 },
|
|
4443
|
+
animate: { opacity: 1, scale: 1 },
|
|
4444
|
+
exit: { opacity: 0, scale: 0.7 },
|
|
4445
|
+
transition: { duration: 0.14, ease: "easeOut" },
|
|
4446
|
+
overflow: "hidden"
|
|
4447
|
+
},
|
|
4448
|
+
blur: {
|
|
4449
|
+
initial: { opacity: 0, filter: "blur(8px)", y: -8 },
|
|
4450
|
+
animate: { opacity: 1, filter: "blur(0px)", y: 0 },
|
|
4451
|
+
exit: { opacity: 0, filter: "blur(8px)", y: 8 },
|
|
4452
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
4453
|
+
overflow: "visible"
|
|
4454
|
+
}
|
|
4455
|
+
};
|
|
4456
|
+
function CharSlot({
|
|
4457
|
+
char,
|
|
4458
|
+
charKey,
|
|
4459
|
+
effect
|
|
4460
|
+
}) {
|
|
4461
|
+
if (!/\d/.test(char)) return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block" }, children: char });
|
|
4462
|
+
const v = CHAR_VARIANTS[effect];
|
|
4463
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { position: "relative", display: "inline-block", overflow: v.overflow }, children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4464
|
+
framerMotion.motion.span,
|
|
4465
|
+
{
|
|
4466
|
+
initial: v.initial,
|
|
4467
|
+
animate: v.animate,
|
|
4468
|
+
exit: v.exit,
|
|
4469
|
+
transition: v.transition,
|
|
4470
|
+
style: { display: "inline-block" },
|
|
4471
|
+
children: char
|
|
4472
|
+
},
|
|
4473
|
+
charKey
|
|
4474
|
+
) }) });
|
|
4475
|
+
}
|
|
4476
|
+
function CountUp({
|
|
4477
|
+
to,
|
|
4478
|
+
from = 0,
|
|
4479
|
+
duration = 2,
|
|
4480
|
+
delay = 0,
|
|
4481
|
+
digitEffect = "none",
|
|
4482
|
+
className,
|
|
4483
|
+
startWhen = true,
|
|
4484
|
+
separator = ""
|
|
4485
|
+
}) {
|
|
4486
|
+
const ref = React.useRef(null);
|
|
4487
|
+
const motionValue = framerMotion.useMotionValue(from);
|
|
4488
|
+
const damping = 20 + 40 * (1 / duration);
|
|
4489
|
+
const stiffness = 100 * (1 / duration);
|
|
4490
|
+
const springValue = framerMotion.useSpring(motionValue, { damping, stiffness });
|
|
4491
|
+
const isInView = framerMotion.useInView(ref, { once: true, margin: "0px" });
|
|
4492
|
+
const decimals = React.useMemo(() => {
|
|
4493
|
+
const d = (n) => {
|
|
4494
|
+
const s = n.toString();
|
|
4495
|
+
return s.includes(".") ? s.split(".")[1].length : 0;
|
|
4496
|
+
};
|
|
4497
|
+
return Math.max(d(from), d(to));
|
|
4498
|
+
}, [from, to]);
|
|
4499
|
+
const formatValue = React.useCallback(
|
|
4500
|
+
(latest) => {
|
|
4501
|
+
const formatted = Intl.NumberFormat("en-US", {
|
|
4502
|
+
useGrouping: !!separator,
|
|
4503
|
+
minimumFractionDigits: decimals,
|
|
4504
|
+
maximumFractionDigits: decimals
|
|
4505
|
+
}).format(latest);
|
|
4506
|
+
return separator ? formatted.replace(/,/g, separator) : formatted;
|
|
4507
|
+
},
|
|
4508
|
+
[decimals, separator]
|
|
4509
|
+
);
|
|
4510
|
+
const [chars, setChars] = React.useState(formatValue(from).split(""));
|
|
4511
|
+
React.useEffect(() => {
|
|
4512
|
+
if (isInView && startWhen) {
|
|
4513
|
+
const t = setTimeout(() => motionValue.set(to), delay * 1e3);
|
|
4514
|
+
return () => clearTimeout(t);
|
|
4515
|
+
}
|
|
4516
|
+
}, [isInView, startWhen, motionValue, to, delay]);
|
|
4517
|
+
React.useEffect(() => {
|
|
4518
|
+
const unsub = springValue.on("change", (latest) => {
|
|
4519
|
+
if (digitEffect === "none") {
|
|
4520
|
+
if (ref.current) ref.current.textContent = formatValue(latest);
|
|
4521
|
+
} else {
|
|
4522
|
+
setChars(formatValue(latest).split(""));
|
|
4523
|
+
}
|
|
4524
|
+
});
|
|
4525
|
+
return () => unsub();
|
|
4526
|
+
}, [springValue, formatValue, digitEffect]);
|
|
4527
|
+
if (digitEffect === "none") {
|
|
4528
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn(className), children: formatValue(from) });
|
|
4529
|
+
}
|
|
4530
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("inline-flex items-center", className), children: chars.map((char, i) => /* @__PURE__ */ jsxRuntime.jsx(CharSlot, { char, charKey: `${i}-${char}`, effect: digitEffect }, i)) });
|
|
4531
|
+
}
|
|
4532
|
+
function AnimatedDuration({ seconds, className }) {
|
|
4533
|
+
const total = Math.max(0, seconds);
|
|
4534
|
+
const m = Math.floor(total / 60);
|
|
4535
|
+
const s = total % 60;
|
|
4536
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("tabular-nums", className), children: [
|
|
4537
|
+
m > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4538
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountUp, { to: m, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4539
|
+
"m",
|
|
4540
|
+
" "
|
|
4541
|
+
] }),
|
|
4542
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountUp, { to: s, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4543
|
+
"s"
|
|
4544
|
+
] });
|
|
4545
|
+
}
|
|
4271
4546
|
var DEFAULT_MAX_LENGTH = 6;
|
|
4272
4547
|
var MAX_SUPPORTED_LENGTH = 12;
|
|
4273
4548
|
var AUTO_FOCUS_DELAY_MS = 250;
|
|
@@ -4278,10 +4553,10 @@ function OtpInputV2({
|
|
|
4278
4553
|
disabled = false,
|
|
4279
4554
|
error = false
|
|
4280
4555
|
}) {
|
|
4281
|
-
const inputRefs =
|
|
4556
|
+
const inputRefs = React.useRef([]);
|
|
4282
4557
|
const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
|
|
4283
4558
|
const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
|
|
4284
|
-
|
|
4559
|
+
React.useEffect(() => {
|
|
4285
4560
|
if (disabled) return;
|
|
4286
4561
|
const timer = window.setTimeout(() => {
|
|
4287
4562
|
inputRefs.current[0]?.focus();
|
|
@@ -4380,31 +4655,30 @@ function VerificationInline({
|
|
|
4380
4655
|
onResend
|
|
4381
4656
|
}) {
|
|
4382
4657
|
const isNumeric = prompt.verificationType !== "ALPHANUMERIC_CODE";
|
|
4383
|
-
const codeLen =
|
|
4384
|
-
const [code, setCode] =
|
|
4385
|
-
const [errored, setErrored] =
|
|
4386
|
-
const [resendSec, setResendSec] =
|
|
4387
|
-
const [hiddenAfterResend, setHiddenAfterResend] =
|
|
4388
|
-
const lastSubmittedRef =
|
|
4389
|
-
const resendTimerRef =
|
|
4658
|
+
const codeLen = React.useMemo(() => codeLengthFromSchema(prompt), [prompt]);
|
|
4659
|
+
const [code, setCode] = React.useState("");
|
|
4660
|
+
const [errored, setErrored] = React.useState(false);
|
|
4661
|
+
const [resendSec, setResendSec] = React.useState(0);
|
|
4662
|
+
const [hiddenAfterResend, setHiddenAfterResend] = React.useState(false);
|
|
4663
|
+
const lastSubmittedRef = React.useRef(null);
|
|
4664
|
+
const resendTimerRef = React.useRef(void 0);
|
|
4390
4665
|
const status = prompt.status;
|
|
4391
4666
|
const busy = status === "submitting";
|
|
4392
4667
|
const stale = status === "stale";
|
|
4393
4668
|
const locked = busy || stale || expired;
|
|
4394
|
-
|
|
4669
|
+
React.useEffect(() => {
|
|
4395
4670
|
if (prompt.subAction === "SubmissionInvalid") {
|
|
4396
4671
|
setErrored(true);
|
|
4397
|
-
setCode("");
|
|
4398
4672
|
lastSubmittedRef.current = null;
|
|
4399
4673
|
}
|
|
4400
4674
|
}, [prompt.subAction, prompt.userActionId]);
|
|
4401
|
-
|
|
4675
|
+
React.useEffect(() => {
|
|
4402
4676
|
setHiddenAfterResend(false);
|
|
4403
4677
|
}, [prompt.expirySeconds, prompt.message, prompt.subAction, prompt.userActionId]);
|
|
4404
|
-
|
|
4678
|
+
React.useEffect(() => {
|
|
4405
4679
|
if (code.length < codeLen) lastSubmittedRef.current = null;
|
|
4406
4680
|
}, [code, codeLen]);
|
|
4407
|
-
const doSubmit =
|
|
4681
|
+
const doSubmit = React.useCallback(
|
|
4408
4682
|
(value) => {
|
|
4409
4683
|
if (locked || !value) return;
|
|
4410
4684
|
if (lastSubmittedRef.current === value) return;
|
|
@@ -4416,20 +4690,20 @@ function VerificationInline({
|
|
|
4416
4690
|
},
|
|
4417
4691
|
[locked, onSubmit, prompt.userActionId]
|
|
4418
4692
|
);
|
|
4419
|
-
|
|
4693
|
+
React.useEffect(() => {
|
|
4420
4694
|
if (!isNumeric || locked) return;
|
|
4421
4695
|
if (code.length === codeLen && /^\d+$/.test(code)) {
|
|
4422
4696
|
doSubmit(code);
|
|
4423
4697
|
}
|
|
4424
4698
|
}, [code, codeLen, doSubmit, isNumeric, locked]);
|
|
4425
|
-
|
|
4699
|
+
React.useEffect(() => {
|
|
4426
4700
|
return () => {
|
|
4427
4701
|
if (typeof resendTimerRef.current === "number") {
|
|
4428
4702
|
window.clearInterval(resendTimerRef.current);
|
|
4429
4703
|
}
|
|
4430
4704
|
};
|
|
4431
4705
|
}, []);
|
|
4432
|
-
const startResendCooldown =
|
|
4706
|
+
const startResendCooldown = React.useCallback(() => {
|
|
4433
4707
|
setResendSec(RESEND_COOLDOWN_S);
|
|
4434
4708
|
if (typeof resendTimerRef.current === "number") {
|
|
4435
4709
|
window.clearInterval(resendTimerRef.current);
|
|
@@ -4447,7 +4721,7 @@ function VerificationInline({
|
|
|
4447
4721
|
});
|
|
4448
4722
|
}, 1e3);
|
|
4449
4723
|
}, []);
|
|
4450
|
-
const handleResend =
|
|
4724
|
+
const handleResend = React.useCallback(async () => {
|
|
4451
4725
|
if (locked || resendSec > 0) return;
|
|
4452
4726
|
setErrored(false);
|
|
4453
4727
|
setCode("");
|
|
@@ -4460,19 +4734,22 @@ function VerificationInline({
|
|
|
4460
4734
|
setHiddenAfterResend(false);
|
|
4461
4735
|
}
|
|
4462
4736
|
}, [locked, onResend, prompt.userActionId, resendSec, startResendCooldown]);
|
|
4463
|
-
const handleCancel =
|
|
4737
|
+
const handleCancel = React.useCallback(() => {
|
|
4464
4738
|
if (busy) return;
|
|
4465
4739
|
void onCancel(prompt.userActionId);
|
|
4466
4740
|
}, [busy, onCancel, prompt.userActionId]);
|
|
4467
|
-
const
|
|
4741
|
+
const promptMessage = prompt.message?.trim();
|
|
4742
|
+
const description = promptMessage || (isNumeric ? `Enter the ${codeLen}-digit code to continue` : "Enter the verification code to continue");
|
|
4743
|
+
const messageFormat = prompt.metadata?.["payman/messageFormat"];
|
|
4744
|
+
const renderMarkdown = !!promptMessage && messageFormat === "markdown";
|
|
4468
4745
|
if (hiddenAfterResend) return null;
|
|
4469
4746
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua", role: "group", "aria-label": "Verification required", children: [
|
|
4470
4747
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4471
4748
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "payman-v2-ua-icon", size: 15, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4472
4749
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-title", children: "Verification required" }),
|
|
4473
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
4750
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsxRuntime.jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4474
4751
|
] }),
|
|
4475
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: description }),
|
|
4752
|
+
renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRendererV2, { content: description }) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: description }),
|
|
4476
4753
|
stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4477
4754
|
isNumeric ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-field", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4478
4755
|
OtpInputV2,
|
|
@@ -4542,6 +4819,228 @@ function VerificationInline({
|
|
|
4542
4819
|
] })
|
|
4543
4820
|
] });
|
|
4544
4821
|
}
|
|
4822
|
+
function AmountFieldV2({
|
|
4823
|
+
id,
|
|
4824
|
+
value,
|
|
4825
|
+
onChange,
|
|
4826
|
+
disabled,
|
|
4827
|
+
className,
|
|
4828
|
+
onEnter
|
|
4829
|
+
}) {
|
|
4830
|
+
const inputRef = React.useRef(null);
|
|
4831
|
+
const digits = digitsFromValue(value);
|
|
4832
|
+
const display = formatDigits(digits);
|
|
4833
|
+
React.useLayoutEffect(() => {
|
|
4834
|
+
const el = inputRef.current;
|
|
4835
|
+
if (el && document.activeElement === el) {
|
|
4836
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
4837
|
+
}
|
|
4838
|
+
}, [display]);
|
|
4839
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4840
|
+
"input",
|
|
4841
|
+
{
|
|
4842
|
+
ref: inputRef,
|
|
4843
|
+
id,
|
|
4844
|
+
type: "text",
|
|
4845
|
+
inputMode: "decimal",
|
|
4846
|
+
autoComplete: "off",
|
|
4847
|
+
className,
|
|
4848
|
+
value: display,
|
|
4849
|
+
placeholder: "0.00",
|
|
4850
|
+
disabled,
|
|
4851
|
+
onChange: (e) => {
|
|
4852
|
+
onChange(valueFromDigits(digitsFromDisplay(e.target.value)));
|
|
4853
|
+
},
|
|
4854
|
+
onKeyDown: (e) => {
|
|
4855
|
+
if (e.key === "Enter") {
|
|
4856
|
+
e.preventDefault();
|
|
4857
|
+
onEnter?.();
|
|
4858
|
+
}
|
|
4859
|
+
},
|
|
4860
|
+
onFocus: (e) => {
|
|
4861
|
+
const el = e.currentTarget;
|
|
4862
|
+
requestAnimationFrame(() => el.setSelectionRange(el.value.length, el.value.length));
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4867
|
+
function digitsFromDisplay(raw) {
|
|
4868
|
+
return raw.replace(/[^0-9]/g, "").replace(/^0+(?=\d)/, "").slice(-9);
|
|
4869
|
+
}
|
|
4870
|
+
function digitsFromValue(value) {
|
|
4871
|
+
const num = Number(value);
|
|
4872
|
+
if (!value || !Number.isFinite(num) || num <= 0) return "";
|
|
4873
|
+
return String(Math.round(num * 100));
|
|
4874
|
+
}
|
|
4875
|
+
function formatDigits(digits) {
|
|
4876
|
+
if (!digits) return "";
|
|
4877
|
+
const padded = digits.padStart(3, "0");
|
|
4878
|
+
const cents = padded.slice(-2);
|
|
4879
|
+
const whole = padded.slice(0, -2).replace(/^0+(?=\d)/, "") || "0";
|
|
4880
|
+
const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
4881
|
+
return `${grouped}.${cents}`;
|
|
4882
|
+
}
|
|
4883
|
+
function valueFromDigits(digits) {
|
|
4884
|
+
if (!digits) return "";
|
|
4885
|
+
return (Number(digits) / 100).toString();
|
|
4886
|
+
}
|
|
4887
|
+
function findRootClassName(el) {
|
|
4888
|
+
const root = el?.closest(".payman-v2-root");
|
|
4889
|
+
return root instanceof HTMLElement ? root.className : "";
|
|
4890
|
+
}
|
|
4891
|
+
var MENU_MAX_HEIGHT = 240;
|
|
4892
|
+
var OPTION_HEIGHT = 34;
|
|
4893
|
+
var VIEWPORT_MARGIN = 8;
|
|
4894
|
+
function SelectFieldV2({
|
|
4895
|
+
id,
|
|
4896
|
+
value,
|
|
4897
|
+
options,
|
|
4898
|
+
onChange,
|
|
4899
|
+
disabled,
|
|
4900
|
+
error,
|
|
4901
|
+
placeholder = "Select\u2026"
|
|
4902
|
+
}) {
|
|
4903
|
+
const triggerRef = React.useRef(null);
|
|
4904
|
+
const listRef = React.useRef(null);
|
|
4905
|
+
const [open, setOpen] = React.useState(false);
|
|
4906
|
+
const [rect, setRect] = React.useState(null);
|
|
4907
|
+
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
4908
|
+
const [rootClassName, setRootClassName] = React.useState("");
|
|
4909
|
+
const selected = options.find((o) => o.const === value);
|
|
4910
|
+
React.useLayoutEffect(() => {
|
|
4911
|
+
if (!open) return;
|
|
4912
|
+
const place = () => {
|
|
4913
|
+
const el = triggerRef.current;
|
|
4914
|
+
if (!el) return;
|
|
4915
|
+
const r = el.getBoundingClientRect();
|
|
4916
|
+
const viewportH = window.innerHeight;
|
|
4917
|
+
const estimatedMenuH = Math.min(
|
|
4918
|
+
options.length * OPTION_HEIGHT + VIEWPORT_MARGIN,
|
|
4919
|
+
MENU_MAX_HEIGHT
|
|
4920
|
+
);
|
|
4921
|
+
const spaceBelow = viewportH - r.bottom;
|
|
4922
|
+
const spaceAbove = r.top;
|
|
4923
|
+
const openUp = spaceBelow < estimatedMenuH && spaceAbove > spaceBelow;
|
|
4924
|
+
setRect({ top: r.bottom, bottom: viewportH - r.top, left: r.left, width: r.width, openUp });
|
|
4925
|
+
setRootClassName(findRootClassName(el));
|
|
4926
|
+
};
|
|
4927
|
+
place();
|
|
4928
|
+
window.addEventListener("resize", place);
|
|
4929
|
+
window.addEventListener("scroll", place, true);
|
|
4930
|
+
return () => {
|
|
4931
|
+
window.removeEventListener("resize", place);
|
|
4932
|
+
window.removeEventListener("scroll", place, true);
|
|
4933
|
+
};
|
|
4934
|
+
}, [open, options.length]);
|
|
4935
|
+
React.useEffect(() => {
|
|
4936
|
+
if (!open) return;
|
|
4937
|
+
setActiveIndex(Math.max(0, options.findIndex((o) => o.const === value)));
|
|
4938
|
+
listRef.current?.focus();
|
|
4939
|
+
}, [open]);
|
|
4940
|
+
React.useEffect(() => {
|
|
4941
|
+
if (!open) return;
|
|
4942
|
+
const onDocDown = (e) => {
|
|
4943
|
+
const target = e.target;
|
|
4944
|
+
if (triggerRef.current?.contains(target) || listRef.current?.contains(target)) return;
|
|
4945
|
+
setOpen(false);
|
|
4946
|
+
};
|
|
4947
|
+
document.addEventListener("mousedown", onDocDown);
|
|
4948
|
+
return () => document.removeEventListener("mousedown", onDocDown);
|
|
4949
|
+
}, [open]);
|
|
4950
|
+
const commit = (opt) => {
|
|
4951
|
+
onChange(opt.const);
|
|
4952
|
+
setOpen(false);
|
|
4953
|
+
triggerRef.current?.focus();
|
|
4954
|
+
};
|
|
4955
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4956
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4957
|
+
"button",
|
|
4958
|
+
{
|
|
4959
|
+
ref: triggerRef,
|
|
4960
|
+
id,
|
|
4961
|
+
type: "button",
|
|
4962
|
+
disabled,
|
|
4963
|
+
className: cn("payman-v2-ua-select-trigger", error && "payman-v2-ua-input-error"),
|
|
4964
|
+
"aria-haspopup": "listbox",
|
|
4965
|
+
"aria-expanded": open,
|
|
4966
|
+
onClick: () => setOpen((v) => !v),
|
|
4967
|
+
onKeyDown: (e) => {
|
|
4968
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
4969
|
+
e.preventDefault();
|
|
4970
|
+
setOpen(true);
|
|
4971
|
+
}
|
|
4972
|
+
},
|
|
4973
|
+
children: [
|
|
4974
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4975
|
+
"span",
|
|
4976
|
+
{
|
|
4977
|
+
className: cn(
|
|
4978
|
+
"payman-v2-ua-select-value",
|
|
4979
|
+
!selected && "payman-v2-ua-select-placeholder"
|
|
4980
|
+
),
|
|
4981
|
+
children: selected ? selected.title || selected.const : placeholder
|
|
4982
|
+
}
|
|
4983
|
+
),
|
|
4984
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, className: "payman-v2-ua-select-chevron", "aria-hidden": true })
|
|
4985
|
+
]
|
|
4986
|
+
}
|
|
4987
|
+
),
|
|
4988
|
+
open && rect && typeof document !== "undefined" && reactDom.createPortal(
|
|
4989
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4990
|
+
"div",
|
|
4991
|
+
{
|
|
4992
|
+
ref: listRef,
|
|
4993
|
+
role: "listbox",
|
|
4994
|
+
className: cn(rootClassName, "payman-v2-ua-select-menu"),
|
|
4995
|
+
tabIndex: -1,
|
|
4996
|
+
style: {
|
|
4997
|
+
position: "fixed",
|
|
4998
|
+
left: rect.left,
|
|
4999
|
+
width: rect.width,
|
|
5000
|
+
height: "fit-content",
|
|
5001
|
+
maxHeight: MENU_MAX_HEIGHT,
|
|
5002
|
+
...rect.openUp ? { bottom: rect.bottom } : { top: rect.top }
|
|
5003
|
+
},
|
|
5004
|
+
onKeyDown: (e) => {
|
|
5005
|
+
if (e.key === "ArrowDown") {
|
|
5006
|
+
e.preventDefault();
|
|
5007
|
+
setActiveIndex((i) => Math.min(options.length - 1, i + 1));
|
|
5008
|
+
} else if (e.key === "ArrowUp") {
|
|
5009
|
+
e.preventDefault();
|
|
5010
|
+
setActiveIndex((i) => Math.max(0, i - 1));
|
|
5011
|
+
} else if (e.key === "Enter" || e.key === " ") {
|
|
5012
|
+
e.preventDefault();
|
|
5013
|
+
if (activeIndex >= 0) commit(options[activeIndex]);
|
|
5014
|
+
} else if (e.key === "Escape" || e.key === "Tab") {
|
|
5015
|
+
setOpen(false);
|
|
5016
|
+
triggerRef.current?.focus();
|
|
5017
|
+
}
|
|
5018
|
+
},
|
|
5019
|
+
children: options.map((opt, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5020
|
+
"div",
|
|
5021
|
+
{
|
|
5022
|
+
role: "option",
|
|
5023
|
+
"aria-selected": opt.const === value,
|
|
5024
|
+
className: cn(
|
|
5025
|
+
"payman-v2-ua-select-option",
|
|
5026
|
+
i === activeIndex && "payman-v2-ua-select-option-active",
|
|
5027
|
+
opt.const === value && "payman-v2-ua-select-option-selected"
|
|
5028
|
+
),
|
|
5029
|
+
onMouseEnter: () => setActiveIndex(i),
|
|
5030
|
+
onClick: () => commit(opt),
|
|
5031
|
+
children: [
|
|
5032
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: opt.title || opt.const }),
|
|
5033
|
+
opt.const === value && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 13, "aria-hidden": true })
|
|
5034
|
+
]
|
|
5035
|
+
},
|
|
5036
|
+
opt.const
|
|
5037
|
+
))
|
|
5038
|
+
}
|
|
5039
|
+
),
|
|
5040
|
+
document.body
|
|
5041
|
+
)
|
|
5042
|
+
] });
|
|
5043
|
+
}
|
|
4545
5044
|
function SchemaFormInline({
|
|
4546
5045
|
prompt,
|
|
4547
5046
|
secondsLeft,
|
|
@@ -4550,13 +5049,13 @@ function SchemaFormInline({
|
|
|
4550
5049
|
onCancel
|
|
4551
5050
|
}) {
|
|
4552
5051
|
const schema = prompt.requestedSchema;
|
|
4553
|
-
const fields =
|
|
4554
|
-
const [values, setValues] =
|
|
5052
|
+
const fields = React.useMemo(() => renderableFields(schema), [schema]);
|
|
5053
|
+
const [values, setValues] = React.useState(() => {
|
|
4555
5054
|
const init2 = {};
|
|
4556
5055
|
for (const [key, field] of fields) init2[key] = defaultValueFor(field);
|
|
4557
5056
|
return init2;
|
|
4558
5057
|
});
|
|
4559
|
-
const [errors, setErrors] =
|
|
5058
|
+
const [errors, setErrors] = React.useState({});
|
|
4560
5059
|
const status = prompt.status;
|
|
4561
5060
|
const busy = status === "submitting";
|
|
4562
5061
|
const stale = status === "stale";
|
|
@@ -4587,7 +5086,7 @@ function SchemaFormInline({
|
|
|
4587
5086
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4588
5087
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "payman-v2-ua-icon", size: 14, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4589
5088
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-title", children: "Action required" }),
|
|
4590
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
5089
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsxRuntime.jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4591
5090
|
] }),
|
|
4592
5091
|
prompt.message?.trim() && (renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRendererV2, { content: prompt.message }) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: prompt.message })),
|
|
4593
5092
|
stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : fields.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-form", children: fields.map(([key, field]) => {
|
|
@@ -4619,26 +5118,33 @@ function SchemaFormInline({
|
|
|
4619
5118
|
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-req", children: "*" })
|
|
4620
5119
|
] }),
|
|
4621
5120
|
field.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-hint", children: field.description }),
|
|
4622
|
-
widget === "select" ? /* @__PURE__ */ jsxRuntime.
|
|
4623
|
-
|
|
5121
|
+
widget === "select" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5122
|
+
SelectFieldV2,
|
|
4624
5123
|
{
|
|
4625
5124
|
id: fieldId,
|
|
4626
|
-
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4627
5125
|
value: String(values[key] ?? ""),
|
|
5126
|
+
options: getOptions(field),
|
|
4628
5127
|
disabled: locked,
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
5128
|
+
error: Boolean(err),
|
|
5129
|
+
onChange: (v) => setValue(key, v)
|
|
5130
|
+
}
|
|
5131
|
+
) : widget === "decimal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5132
|
+
AmountFieldV2,
|
|
5133
|
+
{
|
|
5134
|
+
id: fieldId,
|
|
5135
|
+
value: String(values[key] ?? ""),
|
|
5136
|
+
disabled: locked,
|
|
5137
|
+
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
5138
|
+
onChange: (v) => setValue(key, v),
|
|
5139
|
+
onEnter: handleSubmit
|
|
4634
5140
|
}
|
|
4635
5141
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4636
5142
|
"input",
|
|
4637
5143
|
{
|
|
4638
5144
|
id: fieldId,
|
|
4639
|
-
type: widget === "integer"
|
|
4640
|
-
inputMode: widget === "integer" ? "numeric" :
|
|
4641
|
-
step: widget === "
|
|
5145
|
+
type: widget === "integer" ? "number" : "text",
|
|
5146
|
+
inputMode: widget === "integer" ? "numeric" : void 0,
|
|
5147
|
+
step: widget === "integer" ? "1" : void 0,
|
|
4642
5148
|
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4643
5149
|
value: String(values[key] ?? ""),
|
|
4644
5150
|
disabled: locked,
|
|
@@ -4697,10 +5203,10 @@ function NotificationInline({ notification, onDismiss }) {
|
|
|
4697
5203
|
}
|
|
4698
5204
|
function useExpiryCountdown(prompt) {
|
|
4699
5205
|
const deadlineMs = typeof prompt.expiresAt === "number" && prompt.expiresAt > 0 ? prompt.expiresAt : typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0 ? Date.now() + Math.floor(prompt.expirySeconds) * 1e3 : void 0;
|
|
4700
|
-
const [secondsLeft, setSecondsLeft] =
|
|
5206
|
+
const [secondsLeft, setSecondsLeft] = React.useState(
|
|
4701
5207
|
() => deadlineMs !== void 0 ? Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1e3)) : void 0
|
|
4702
5208
|
);
|
|
4703
|
-
|
|
5209
|
+
React.useEffect(() => {
|
|
4704
5210
|
if (deadlineMs === void 0) {
|
|
4705
5211
|
setSecondsLeft(void 0);
|
|
4706
5212
|
return;
|
|
@@ -4735,12 +5241,16 @@ function UserActionInline({
|
|
|
4735
5241
|
onSubmit,
|
|
4736
5242
|
onCancel,
|
|
4737
5243
|
onResend,
|
|
4738
|
-
onExpired
|
|
5244
|
+
onExpired,
|
|
5245
|
+
suppressExpiredNote
|
|
4739
5246
|
}) {
|
|
4740
5247
|
const [secondsLeft, expired] = useExpiryCountdown(prompt);
|
|
4741
|
-
|
|
5248
|
+
React.useEffect(() => {
|
|
4742
5249
|
if (expired && prompt.kind !== "notification") onExpired?.();
|
|
4743
5250
|
}, [expired, onExpired, prompt.kind]);
|
|
5251
|
+
if (expired && prompt.kind !== "notification" && suppressExpiredNote) {
|
|
5252
|
+
return null;
|
|
5253
|
+
}
|
|
4744
5254
|
let body;
|
|
4745
5255
|
if (expired && prompt.kind !== "notification") {
|
|
4746
5256
|
const note = {
|
|
@@ -4801,7 +5311,10 @@ function getPromptViewKey(prompt) {
|
|
|
4801
5311
|
prompt.message ?? ""
|
|
4802
5312
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4803
5313
|
}
|
|
4804
|
-
|
|
5314
|
+
function getPromptMountKey(prompt) {
|
|
5315
|
+
return [getPromptSlotKey(prompt), prompt.userActionId].join(PROMPT_KEY_SEPARATOR);
|
|
5316
|
+
}
|
|
5317
|
+
var MessageListV2 = React.forwardRef(
|
|
4805
5318
|
function MessageListV22({
|
|
4806
5319
|
messages,
|
|
4807
5320
|
isStreaming = false,
|
|
@@ -4812,6 +5325,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4812
5325
|
messageActions,
|
|
4813
5326
|
retryDisabled = false,
|
|
4814
5327
|
userActionPrompts,
|
|
5328
|
+
dockedUserActionId,
|
|
4815
5329
|
notifications,
|
|
4816
5330
|
onSubmitUserAction,
|
|
4817
5331
|
onCancelUserAction,
|
|
@@ -4821,25 +5335,25 @@ var MessageListV2 = react.forwardRef(
|
|
|
4821
5335
|
onSubmitFeedback,
|
|
4822
5336
|
typingSpeed = 4
|
|
4823
5337
|
}, ref) {
|
|
4824
|
-
const noop =
|
|
5338
|
+
const noop = React.useCallback(async () => {
|
|
4825
5339
|
}, []);
|
|
4826
|
-
const scrollRef =
|
|
4827
|
-
const scrollInnerRef =
|
|
4828
|
-
const isNearBottomRef =
|
|
4829
|
-
const [showScrollBtn, setShowScrollBtn] =
|
|
4830
|
-
const [expiredPromptViewState, setExpiredPromptViewState] =
|
|
4831
|
-
const expiredUserActionIdsRef =
|
|
4832
|
-
const prevCountRef =
|
|
4833
|
-
const pauseStickUntilUserMessageRef =
|
|
4834
|
-
const followingBottomRef =
|
|
4835
|
-
const lastPinAtRef =
|
|
4836
|
-
const prevScrollTopRef =
|
|
4837
|
-
const getDistanceFromBottom =
|
|
5340
|
+
const scrollRef = React.useRef(null);
|
|
5341
|
+
const scrollInnerRef = React.useRef(null);
|
|
5342
|
+
const isNearBottomRef = React.useRef(true);
|
|
5343
|
+
const [showScrollBtn, setShowScrollBtn] = React.useState(false);
|
|
5344
|
+
const [expiredPromptViewState, setExpiredPromptViewState] = React.useState({});
|
|
5345
|
+
const expiredUserActionIdsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
5346
|
+
const prevCountRef = React.useRef(messages.length);
|
|
5347
|
+
const pauseStickUntilUserMessageRef = React.useRef(false);
|
|
5348
|
+
const followingBottomRef = React.useRef(true);
|
|
5349
|
+
const lastPinAtRef = React.useRef(0);
|
|
5350
|
+
const prevScrollTopRef = React.useRef(0);
|
|
5351
|
+
const getDistanceFromBottom = React.useCallback(() => {
|
|
4838
5352
|
const el = scrollRef.current;
|
|
4839
5353
|
if (!el) return 0;
|
|
4840
5354
|
return el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
4841
5355
|
}, []);
|
|
4842
|
-
const messageActivityFingerprint =
|
|
5356
|
+
const messageActivityFingerprint = React.useMemo(() => {
|
|
4843
5357
|
const last = messages[messages.length - 1];
|
|
4844
5358
|
const promptFingerprint = (userActionPrompts ?? []).map((prompt) => `${getPromptViewKey(prompt)}:${prompt.status}`).join(PROMPT_KEY_SEPARATOR);
|
|
4845
5359
|
const notificationFingerprint = (notifications ?? []).map((notification) => notification.id).join(PROMPT_KEY_SEPARATOR);
|
|
@@ -4865,7 +5379,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4865
5379
|
notificationFingerprint
|
|
4866
5380
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4867
5381
|
}, [isStreaming, messages, notifications, userActionPrompts]);
|
|
4868
|
-
const handleUserActionExpired =
|
|
5382
|
+
const handleUserActionExpired = React.useCallback(
|
|
4869
5383
|
(promptKey, userActionId) => {
|
|
4870
5384
|
setExpiredPromptViewState((prev) => {
|
|
4871
5385
|
if (prev[promptKey]) return prev;
|
|
@@ -4882,7 +5396,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4882
5396
|
},
|
|
4883
5397
|
[messageActivityFingerprint, onExpireUserAction]
|
|
4884
5398
|
);
|
|
4885
|
-
|
|
5399
|
+
React.useEffect(() => {
|
|
4886
5400
|
setExpiredPromptViewState((prev) => {
|
|
4887
5401
|
let changed = false;
|
|
4888
5402
|
const next = {};
|
|
@@ -4897,7 +5411,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4897
5411
|
return changed ? next : prev;
|
|
4898
5412
|
});
|
|
4899
5413
|
}, [messageActivityFingerprint]);
|
|
4900
|
-
|
|
5414
|
+
React.useEffect(() => {
|
|
4901
5415
|
const livePromptKeys = new Set((userActionPrompts ?? []).map(getPromptViewKey));
|
|
4902
5416
|
const liveUserActionIds = new Set((userActionPrompts ?? []).map((p) => p.userActionId));
|
|
4903
5417
|
for (const userActionId of expiredUserActionIdsRef.current) {
|
|
@@ -4918,21 +5432,22 @@ var MessageListV2 = react.forwardRef(
|
|
|
4918
5432
|
return changed ? next : prev;
|
|
4919
5433
|
});
|
|
4920
5434
|
}, [userActionPrompts]);
|
|
4921
|
-
const visibleUserActionPrompts =
|
|
5435
|
+
const visibleUserActionPrompts = React.useMemo(
|
|
4922
5436
|
() => userActionPrompts?.filter((prompt) => {
|
|
5437
|
+
if (prompt.userActionId === dockedUserActionId) return false;
|
|
4923
5438
|
const promptKey = getPromptViewKey(prompt);
|
|
4924
5439
|
return !expiredPromptViewState[promptKey]?.hidden;
|
|
4925
5440
|
}),
|
|
4926
|
-
[expiredPromptViewState, userActionPrompts]
|
|
5441
|
+
[dockedUserActionId, expiredPromptViewState, userActionPrompts]
|
|
4927
5442
|
);
|
|
4928
|
-
const pinToBottom =
|
|
5443
|
+
const pinToBottom = React.useCallback((behavior = "instant") => {
|
|
4929
5444
|
const el = scrollRef.current;
|
|
4930
5445
|
if (!el) return;
|
|
4931
5446
|
lastPinAtRef.current = performance.now();
|
|
4932
5447
|
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
4933
5448
|
prevScrollTopRef.current = el.scrollHeight;
|
|
4934
5449
|
}, []);
|
|
4935
|
-
const scrollToBottom =
|
|
5450
|
+
const scrollToBottom = React.useCallback(
|
|
4936
5451
|
(behavior = "smooth") => {
|
|
4937
5452
|
const el = scrollRef.current;
|
|
4938
5453
|
if (!el) return;
|
|
@@ -4942,7 +5457,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4942
5457
|
},
|
|
4943
5458
|
[pinToBottom]
|
|
4944
5459
|
);
|
|
4945
|
-
|
|
5460
|
+
React.useImperativeHandle(
|
|
4946
5461
|
ref,
|
|
4947
5462
|
() => ({
|
|
4948
5463
|
scrollToBottom: (behavior = "smooth") => {
|
|
@@ -4955,7 +5470,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4955
5470
|
}),
|
|
4956
5471
|
[scrollToBottom]
|
|
4957
5472
|
);
|
|
4958
|
-
const handleScroll =
|
|
5473
|
+
const handleScroll = React.useCallback(() => {
|
|
4959
5474
|
const el = scrollRef.current;
|
|
4960
5475
|
if (!el) return;
|
|
4961
5476
|
const currentScrollTop = el.scrollTop;
|
|
@@ -4976,7 +5491,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4976
5491
|
pauseStickUntilUserMessageRef.current = false;
|
|
4977
5492
|
}
|
|
4978
5493
|
}, [getDistanceFromBottom]);
|
|
4979
|
-
|
|
5494
|
+
React.useEffect(() => {
|
|
4980
5495
|
const prevCount = prevCountRef.current;
|
|
4981
5496
|
prevCountRef.current = messages.length;
|
|
4982
5497
|
if (messages.length > prevCount) {
|
|
@@ -4990,7 +5505,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4990
5505
|
}
|
|
4991
5506
|
}
|
|
4992
5507
|
}, [messages.length, scrollToBottom]);
|
|
4993
|
-
|
|
5508
|
+
React.useEffect(() => {
|
|
4994
5509
|
const inner = scrollInnerRef.current;
|
|
4995
5510
|
if (!inner) return;
|
|
4996
5511
|
const pinIfFollowing = () => {
|
|
@@ -5015,7 +5530,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
5015
5530
|
mo.disconnect();
|
|
5016
5531
|
};
|
|
5017
5532
|
}, [pinToBottom]);
|
|
5018
|
-
|
|
5533
|
+
React.useEffect(() => {
|
|
5019
5534
|
if (messages.length > 0) {
|
|
5020
5535
|
setTimeout(() => scrollToBottom("instant"), 50);
|
|
5021
5536
|
}
|
|
@@ -5072,7 +5587,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
5072
5587
|
onResend: onResendUserAction ?? noop,
|
|
5073
5588
|
onExpired: () => handleUserActionExpired(promptKey, prompt.userActionId)
|
|
5074
5589
|
},
|
|
5075
|
-
|
|
5590
|
+
getPromptMountKey(prompt)
|
|
5076
5591
|
);
|
|
5077
5592
|
})
|
|
5078
5593
|
]
|
|
@@ -5104,7 +5619,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
5104
5619
|
] });
|
|
5105
5620
|
}
|
|
5106
5621
|
);
|
|
5107
|
-
var ChatInputV2 =
|
|
5622
|
+
var ChatInputV2 = React.forwardRef(
|
|
5108
5623
|
function ChatInputV22({
|
|
5109
5624
|
onSend,
|
|
5110
5625
|
disabled = false,
|
|
@@ -5128,20 +5643,20 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5128
5643
|
onAnalysisModeChange,
|
|
5129
5644
|
slashCommands = []
|
|
5130
5645
|
}, ref) {
|
|
5131
|
-
const [value, setValue] =
|
|
5132
|
-
const [isFocused, setIsFocused] =
|
|
5133
|
-
const [showActions, setShowActions] =
|
|
5134
|
-
const [showVoiceTooltip, setShowVoiceTooltip] =
|
|
5135
|
-
const [selectedCommandIndex, setSelectedCommandIndex] =
|
|
5136
|
-
const [inlineHint, setInlineHint] =
|
|
5137
|
-
const [commandMenuDismissed, setCommandMenuDismissed] =
|
|
5138
|
-
const textareaRef =
|
|
5139
|
-
const actionsRef =
|
|
5140
|
-
const preRecordTextRef =
|
|
5141
|
-
const voiceTooltipTimerRef =
|
|
5646
|
+
const [value, setValue] = React.useState("");
|
|
5647
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
5648
|
+
const [showActions, setShowActions] = React.useState(false);
|
|
5649
|
+
const [showVoiceTooltip, setShowVoiceTooltip] = React.useState(false);
|
|
5650
|
+
const [selectedCommandIndex, setSelectedCommandIndex] = React.useState(0);
|
|
5651
|
+
const [inlineHint, setInlineHint] = React.useState(null);
|
|
5652
|
+
const [commandMenuDismissed, setCommandMenuDismissed] = React.useState(false);
|
|
5653
|
+
const textareaRef = React.useRef(null);
|
|
5654
|
+
const actionsRef = React.useRef(null);
|
|
5655
|
+
const preRecordTextRef = React.useRef("");
|
|
5656
|
+
const voiceTooltipTimerRef = React.useRef(
|
|
5142
5657
|
null
|
|
5143
5658
|
);
|
|
5144
|
-
const voiceDraftSyncActiveRef =
|
|
5659
|
+
const voiceDraftSyncActiveRef = React.useRef(false);
|
|
5145
5660
|
const isInputLocked = disabled || isRecording;
|
|
5146
5661
|
const hasAttachmentOptions = showUploadImageButton || showAttachFileButton;
|
|
5147
5662
|
const showAttachmentMenuButton = showAttachmentButton && hasAttachmentOptions;
|
|
@@ -5152,14 +5667,14 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5152
5667
|
(command) => command.name.toLowerCase().startsWith(commandQuery)
|
|
5153
5668
|
);
|
|
5154
5669
|
const showCommandSuggestions = !commandMenuDismissed && !isRecording && !disabled && commandSuggestions.length > 0;
|
|
5155
|
-
|
|
5670
|
+
React.useEffect(() => {
|
|
5156
5671
|
if (textareaRef.current) {
|
|
5157
5672
|
textareaRef.current.style.height = "auto";
|
|
5158
5673
|
const scrollHeight = textareaRef.current.scrollHeight;
|
|
5159
5674
|
textareaRef.current.style.height = `${Math.min(scrollHeight, 200)}px`;
|
|
5160
5675
|
}
|
|
5161
5676
|
}, [value]);
|
|
5162
|
-
|
|
5677
|
+
React.useEffect(() => {
|
|
5163
5678
|
if (disabled) {
|
|
5164
5679
|
setIsFocused(false);
|
|
5165
5680
|
setShowActions(false);
|
|
@@ -5169,7 +5684,7 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5169
5684
|
const frameId = requestAnimationFrame(() => textareaRef.current?.focus());
|
|
5170
5685
|
return () => cancelAnimationFrame(frameId);
|
|
5171
5686
|
}, [disabled]);
|
|
5172
|
-
|
|
5687
|
+
React.useImperativeHandle(
|
|
5173
5688
|
ref,
|
|
5174
5689
|
() => ({
|
|
5175
5690
|
setDraft: (message) => {
|
|
@@ -5186,7 +5701,7 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5186
5701
|
}),
|
|
5187
5702
|
[disabled]
|
|
5188
5703
|
);
|
|
5189
|
-
|
|
5704
|
+
React.useEffect(() => {
|
|
5190
5705
|
if (!showActions) return;
|
|
5191
5706
|
const handleClickOutside = (e) => {
|
|
5192
5707
|
if (actionsRef.current && !actionsRef.current.contains(e.target)) {
|
|
@@ -5196,29 +5711,29 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5196
5711
|
document.addEventListener("mousedown", handleClickOutside);
|
|
5197
5712
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
5198
5713
|
}, [showActions]);
|
|
5199
|
-
|
|
5714
|
+
React.useEffect(() => {
|
|
5200
5715
|
if (!showAttachmentMenuButton) {
|
|
5201
5716
|
setShowActions(false);
|
|
5202
5717
|
}
|
|
5203
5718
|
}, [showAttachmentMenuButton]);
|
|
5204
|
-
|
|
5719
|
+
React.useEffect(() => {
|
|
5205
5720
|
setSelectedCommandIndex(0);
|
|
5206
5721
|
setCommandMenuDismissed(false);
|
|
5207
5722
|
}, [commandQuery]);
|
|
5208
|
-
|
|
5723
|
+
React.useEffect(() => {
|
|
5209
5724
|
return () => {
|
|
5210
5725
|
if (voiceTooltipTimerRef.current) {
|
|
5211
5726
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
5212
5727
|
}
|
|
5213
5728
|
};
|
|
5214
5729
|
}, []);
|
|
5215
|
-
|
|
5730
|
+
React.useEffect(() => {
|
|
5216
5731
|
if (!voiceDraftSyncActiveRef.current) return;
|
|
5217
5732
|
const base = preRecordTextRef.current;
|
|
5218
5733
|
const separator = base && !base.endsWith(" ") && transcribedText ? " " : "";
|
|
5219
5734
|
setValue(`${base}${separator}${transcribedText}`);
|
|
5220
5735
|
}, [isRecording, transcribedText]);
|
|
5221
|
-
const handleSend =
|
|
5736
|
+
const handleSend = React.useCallback(() => {
|
|
5222
5737
|
if (!value.trim() || disabled) return;
|
|
5223
5738
|
const commandHint = getSlashCommandValidationHint(value);
|
|
5224
5739
|
if (commandHint) {
|
|
@@ -5238,7 +5753,7 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5238
5753
|
}
|
|
5239
5754
|
});
|
|
5240
5755
|
}, [value, disabled, onClearEditing, onSend]);
|
|
5241
|
-
const selectCommand =
|
|
5756
|
+
const selectCommand = React.useCallback(
|
|
5242
5757
|
(command) => {
|
|
5243
5758
|
const insertText = command.insertText ?? `${command.name} `;
|
|
5244
5759
|
setValue(insertText);
|
|
@@ -5294,14 +5809,14 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5294
5809
|
onAttachFileClick?.();
|
|
5295
5810
|
setShowActions(false);
|
|
5296
5811
|
};
|
|
5297
|
-
const hideVoiceTooltip =
|
|
5812
|
+
const hideVoiceTooltip = React.useCallback(() => {
|
|
5298
5813
|
if (voiceTooltipTimerRef.current) {
|
|
5299
5814
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
5300
5815
|
voiceTooltipTimerRef.current = null;
|
|
5301
5816
|
}
|
|
5302
5817
|
setShowVoiceTooltip(false);
|
|
5303
5818
|
}, []);
|
|
5304
|
-
const startVoiceTooltipTimer =
|
|
5819
|
+
const startVoiceTooltipTimer = React.useCallback(() => {
|
|
5305
5820
|
if (isVoiceButtonDisabled || isRecording) return;
|
|
5306
5821
|
if (voiceTooltipTimerRef.current) {
|
|
5307
5822
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
@@ -5618,14 +6133,459 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5618
6133
|
] });
|
|
5619
6134
|
}
|
|
5620
6135
|
);
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
6136
|
+
function dockKey(prompt) {
|
|
6137
|
+
return `${prompt.toolCallId || prompt.userActionId}:${prompt.userActionId}`;
|
|
6138
|
+
}
|
|
6139
|
+
function UserActionDock({
|
|
6140
|
+
prompt,
|
|
6141
|
+
onSubmit,
|
|
6142
|
+
onCancel,
|
|
6143
|
+
onResend,
|
|
6144
|
+
onExpired,
|
|
6145
|
+
children
|
|
6146
|
+
}) {
|
|
6147
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-dock", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.motion.div, { layout: "size", transition: { duration: 0.3, ease: [0.2, 0, 0, 1] }, children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", initial: false, children: prompt ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6148
|
+
framerMotion.motion.div,
|
|
6149
|
+
{
|
|
6150
|
+
initial: { opacity: 0 },
|
|
6151
|
+
animate: { opacity: 1 },
|
|
6152
|
+
exit: { opacity: 0 },
|
|
6153
|
+
transition: { duration: 0.15 },
|
|
6154
|
+
className: "payman-v2-ua-dock-panel",
|
|
6155
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6156
|
+
UserActionInline,
|
|
6157
|
+
{
|
|
6158
|
+
prompt,
|
|
6159
|
+
onSubmit,
|
|
6160
|
+
onCancel,
|
|
6161
|
+
onResend,
|
|
6162
|
+
onExpired: () => onExpired?.(prompt.userActionId),
|
|
6163
|
+
suppressExpiredNote: true
|
|
6164
|
+
}
|
|
6165
|
+
)
|
|
6166
|
+
},
|
|
6167
|
+
dockKey(prompt)
|
|
6168
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6169
|
+
framerMotion.motion.div,
|
|
6170
|
+
{
|
|
6171
|
+
initial: { opacity: 0 },
|
|
6172
|
+
animate: { opacity: 1 },
|
|
6173
|
+
exit: { opacity: 0 },
|
|
6174
|
+
transition: { duration: 0.15 },
|
|
6175
|
+
children
|
|
6176
|
+
},
|
|
6177
|
+
"composer"
|
|
6178
|
+
) }) }) });
|
|
6179
|
+
}
|
|
6180
|
+
function clamp(value) {
|
|
6181
|
+
return Math.max(0, Math.min(1, value));
|
|
6182
|
+
}
|
|
6183
|
+
function ensureFrameSize(frame, rows, cols) {
|
|
6184
|
+
const result = [];
|
|
6185
|
+
for (let r = 0; r < rows; r++) {
|
|
6186
|
+
const row = frame[r] || [];
|
|
6187
|
+
result.push([]);
|
|
6188
|
+
for (let c = 0; c < cols; c++) {
|
|
6189
|
+
result[r][c] = row[c] ?? 0;
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
return result;
|
|
6193
|
+
}
|
|
6194
|
+
function useAnimation(frames, options) {
|
|
6195
|
+
const [frameIndex, setFrameIndex] = React.useState(0);
|
|
6196
|
+
const [isPlaying, setIsPlaying] = React.useState(options.autoplay);
|
|
6197
|
+
const frameIdRef = React.useRef(void 0);
|
|
6198
|
+
const lastTimeRef = React.useRef(0);
|
|
6199
|
+
const accumulatorRef = React.useRef(0);
|
|
6200
|
+
React.useEffect(() => {
|
|
6201
|
+
if (!frames || frames.length === 0 || !isPlaying) {
|
|
6202
|
+
return;
|
|
6203
|
+
}
|
|
6204
|
+
const frameInterval = 1e3 / options.fps;
|
|
6205
|
+
const animate = (currentTime) => {
|
|
6206
|
+
if (lastTimeRef.current === 0) {
|
|
6207
|
+
lastTimeRef.current = currentTime;
|
|
6208
|
+
}
|
|
6209
|
+
const deltaTime = currentTime - lastTimeRef.current;
|
|
6210
|
+
lastTimeRef.current = currentTime;
|
|
6211
|
+
accumulatorRef.current += deltaTime;
|
|
6212
|
+
if (accumulatorRef.current >= frameInterval) {
|
|
6213
|
+
accumulatorRef.current -= frameInterval;
|
|
6214
|
+
setFrameIndex((prev) => {
|
|
6215
|
+
const next = prev + 1;
|
|
6216
|
+
if (next >= frames.length) {
|
|
6217
|
+
if (options.loop) {
|
|
6218
|
+
options.onFrame?.(0);
|
|
6219
|
+
return 0;
|
|
6220
|
+
} else {
|
|
6221
|
+
setIsPlaying(false);
|
|
6222
|
+
return prev;
|
|
6223
|
+
}
|
|
6224
|
+
}
|
|
6225
|
+
options.onFrame?.(next);
|
|
6226
|
+
return next;
|
|
6227
|
+
});
|
|
6228
|
+
}
|
|
6229
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6230
|
+
};
|
|
6231
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6232
|
+
return () => {
|
|
6233
|
+
if (frameIdRef.current) {
|
|
6234
|
+
cancelAnimationFrame(frameIdRef.current);
|
|
6235
|
+
}
|
|
6236
|
+
};
|
|
6237
|
+
}, [frames, isPlaying, options.fps, options.loop, options.onFrame]);
|
|
6238
|
+
React.useEffect(() => {
|
|
6239
|
+
setFrameIndex(0);
|
|
6240
|
+
setIsPlaying(options.autoplay);
|
|
6241
|
+
lastTimeRef.current = 0;
|
|
6242
|
+
accumulatorRef.current = 0;
|
|
6243
|
+
}, [frames, options.autoplay]);
|
|
6244
|
+
return { frameIndex, isPlaying };
|
|
6245
|
+
}
|
|
6246
|
+
function emptyFrame(rows, cols) {
|
|
6247
|
+
return Array.from({ length: rows }, () => Array(cols).fill(0));
|
|
6248
|
+
}
|
|
6249
|
+
function setPixel(frame, row, col, value) {
|
|
6250
|
+
if (row >= 0 && row < frame.length && col >= 0 && col < frame[0].length) {
|
|
6251
|
+
frame[row][col] = value;
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
var loader = (() => {
|
|
6255
|
+
const frames = [];
|
|
6256
|
+
const size = 7;
|
|
6257
|
+
const center = 3;
|
|
6258
|
+
const radius = 2.5;
|
|
6259
|
+
for (let frame = 0; frame < 12; frame++) {
|
|
6260
|
+
const f = emptyFrame(size, size);
|
|
6261
|
+
for (let i = 0; i < 8; i++) {
|
|
6262
|
+
const angle = frame / 12 * Math.PI * 2 + i / 8 * Math.PI * 2;
|
|
6263
|
+
const x = Math.round(center + Math.cos(angle) * radius);
|
|
6264
|
+
const y = Math.round(center + Math.sin(angle) * radius);
|
|
6265
|
+
const brightness = 1 - i / 10;
|
|
6266
|
+
setPixel(f, y, x, Math.max(0.2, brightness));
|
|
6267
|
+
}
|
|
6268
|
+
frames.push(f);
|
|
6269
|
+
}
|
|
6270
|
+
return frames;
|
|
6271
|
+
})();
|
|
6272
|
+
var pulse = (() => {
|
|
6273
|
+
const frames = [];
|
|
6274
|
+
const size = 7;
|
|
6275
|
+
const center = 3;
|
|
6276
|
+
for (let frame = 0; frame < 16; frame++) {
|
|
6277
|
+
const f = emptyFrame(size, size);
|
|
6278
|
+
const phase = frame / 16 * Math.PI * 2;
|
|
6279
|
+
const intensity = (Math.sin(phase) + 1) / 2;
|
|
6280
|
+
setPixel(f, center, center, 1);
|
|
6281
|
+
const radius = Math.floor((1 - intensity) * 3) + 1;
|
|
6282
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
6283
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
6284
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
6285
|
+
if (Math.abs(dist - radius) < 0.7) {
|
|
6286
|
+
setPixel(f, center + dy, center + dx, intensity * 0.6);
|
|
6287
|
+
}
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6290
|
+
frames.push(f);
|
|
6291
|
+
}
|
|
6292
|
+
return frames;
|
|
6293
|
+
})();
|
|
6294
|
+
function vu(columns, levels) {
|
|
6295
|
+
const rows = 7;
|
|
6296
|
+
const frame = emptyFrame(rows, columns);
|
|
6297
|
+
for (let col = 0; col < Math.min(columns, levels.length); col++) {
|
|
6298
|
+
const level = Math.max(0, Math.min(1, levels[col]));
|
|
6299
|
+
const height = Math.floor(level * rows);
|
|
6300
|
+
for (let row = 0; row < rows; row++) {
|
|
6301
|
+
const rowFromBottom = rows - 1 - row;
|
|
6302
|
+
if (rowFromBottom < height) {
|
|
6303
|
+
let brightness = 1;
|
|
6304
|
+
if (row < rows * 0.3) {
|
|
6305
|
+
brightness = 1;
|
|
6306
|
+
} else if (row < rows * 0.6) {
|
|
6307
|
+
brightness = 0.8;
|
|
6308
|
+
} else {
|
|
6309
|
+
brightness = 0.6;
|
|
6310
|
+
}
|
|
6311
|
+
frame[row][col] = brightness;
|
|
6312
|
+
}
|
|
6313
|
+
}
|
|
6314
|
+
}
|
|
6315
|
+
return frame;
|
|
6316
|
+
}
|
|
6317
|
+
var wave = (() => {
|
|
6318
|
+
const frames = [];
|
|
6319
|
+
const rows = 7;
|
|
6320
|
+
const cols = 7;
|
|
6321
|
+
for (let frame = 0; frame < 24; frame++) {
|
|
6322
|
+
const f = emptyFrame(rows, cols);
|
|
6323
|
+
const phase = frame / 24 * Math.PI * 2;
|
|
6324
|
+
for (let col = 0; col < cols; col++) {
|
|
6325
|
+
const colPhase = col / cols * Math.PI * 2;
|
|
6326
|
+
const height = Math.sin(phase + colPhase) * 2.5 + 3.5;
|
|
6327
|
+
const row = Math.floor(height);
|
|
6328
|
+
if (row >= 0 && row < rows) {
|
|
6329
|
+
setPixel(f, row, col, 1);
|
|
6330
|
+
const frac = height - row;
|
|
6331
|
+
if (row > 0) setPixel(f, row - 1, col, 1 - frac);
|
|
6332
|
+
if (row < rows - 1) setPixel(f, row + 1, col, frac);
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
frames.push(f);
|
|
6336
|
+
}
|
|
6337
|
+
return frames;
|
|
6338
|
+
})();
|
|
6339
|
+
var snake = (() => {
|
|
6340
|
+
const frames = [];
|
|
6341
|
+
const rows = 7;
|
|
6342
|
+
const cols = 7;
|
|
6343
|
+
const path = [];
|
|
6344
|
+
let x = 0;
|
|
6345
|
+
let y = 0;
|
|
6346
|
+
let dx = 1;
|
|
6347
|
+
let dy = 0;
|
|
6348
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6349
|
+
while (path.length < rows * cols) {
|
|
6350
|
+
path.push([y, x]);
|
|
6351
|
+
visited.add(`${y},${x}`);
|
|
6352
|
+
const nextX = x + dx;
|
|
6353
|
+
const nextY = y + dy;
|
|
6354
|
+
if (nextX >= 0 && nextX < cols && nextY >= 0 && nextY < rows && !visited.has(`${nextY},${nextX}`)) {
|
|
6355
|
+
x = nextX;
|
|
6356
|
+
y = nextY;
|
|
6357
|
+
} else {
|
|
6358
|
+
const newDx = -dy;
|
|
6359
|
+
const newDy = dx;
|
|
6360
|
+
dx = newDx;
|
|
6361
|
+
dy = newDy;
|
|
6362
|
+
const nextX2 = x + dx;
|
|
6363
|
+
const nextY2 = y + dy;
|
|
6364
|
+
if (nextX2 >= 0 && nextX2 < cols && nextY2 >= 0 && nextY2 < rows && !visited.has(`${nextY2},${nextX2}`)) {
|
|
6365
|
+
x = nextX2;
|
|
6366
|
+
y = nextY2;
|
|
6367
|
+
} else {
|
|
6368
|
+
break;
|
|
6369
|
+
}
|
|
6370
|
+
}
|
|
6371
|
+
}
|
|
6372
|
+
const snakeLength = 5;
|
|
6373
|
+
for (let frame = 0; frame < path.length; frame++) {
|
|
6374
|
+
const f = emptyFrame(rows, cols);
|
|
6375
|
+
for (let i = 0; i < snakeLength; i++) {
|
|
6376
|
+
const idx = frame - i;
|
|
6377
|
+
if (idx >= 0 && idx < path.length) {
|
|
6378
|
+
const [y2, x2] = path[idx];
|
|
6379
|
+
const brightness = 1 - i / snakeLength;
|
|
6380
|
+
setPixel(f, y2, x2, brightness);
|
|
6381
|
+
}
|
|
6382
|
+
}
|
|
6383
|
+
frames.push(f);
|
|
6384
|
+
}
|
|
6385
|
+
return frames;
|
|
6386
|
+
})();
|
|
6387
|
+
var Matrix = React__namespace.forwardRef(
|
|
6388
|
+
({
|
|
6389
|
+
rows,
|
|
6390
|
+
cols,
|
|
6391
|
+
pattern,
|
|
6392
|
+
frames,
|
|
6393
|
+
fps = 12,
|
|
6394
|
+
autoplay = true,
|
|
6395
|
+
loop = true,
|
|
6396
|
+
size = 10,
|
|
6397
|
+
gap = 2,
|
|
6398
|
+
palette = {
|
|
6399
|
+
on: "currentColor",
|
|
6400
|
+
off: "var(--muted-foreground)"
|
|
6401
|
+
},
|
|
6402
|
+
brightness = 1,
|
|
6403
|
+
ariaLabel,
|
|
6404
|
+
onFrame,
|
|
6405
|
+
mode = "default",
|
|
6406
|
+
levels,
|
|
6407
|
+
className,
|
|
6408
|
+
...props
|
|
6409
|
+
}, ref) => {
|
|
6410
|
+
const { frameIndex } = useAnimation(frames, {
|
|
6411
|
+
fps,
|
|
6412
|
+
autoplay: autoplay && !pattern,
|
|
6413
|
+
loop,
|
|
6414
|
+
onFrame
|
|
6415
|
+
});
|
|
6416
|
+
const currentFrame = React.useMemo(() => {
|
|
6417
|
+
if (mode === "vu" && levels && levels.length > 0) {
|
|
6418
|
+
return ensureFrameSize(vu(cols, levels), rows, cols);
|
|
6419
|
+
}
|
|
6420
|
+
if (pattern) {
|
|
6421
|
+
return ensureFrameSize(pattern, rows, cols);
|
|
6422
|
+
}
|
|
6423
|
+
if (frames && frames.length > 0) {
|
|
6424
|
+
return ensureFrameSize(frames[frameIndex] || frames[0], rows, cols);
|
|
6425
|
+
}
|
|
6426
|
+
return ensureFrameSize([], rows, cols);
|
|
6427
|
+
}, [pattern, frames, frameIndex, rows, cols, mode, levels]);
|
|
6428
|
+
const cellPositions = React.useMemo(() => {
|
|
6429
|
+
const positions = [];
|
|
6430
|
+
for (let row = 0; row < rows; row++) {
|
|
6431
|
+
positions[row] = [];
|
|
6432
|
+
for (let col = 0; col < cols; col++) {
|
|
6433
|
+
positions[row][col] = {
|
|
6434
|
+
x: col * (size + gap),
|
|
6435
|
+
y: row * (size + gap)
|
|
6436
|
+
};
|
|
6437
|
+
}
|
|
6438
|
+
}
|
|
6439
|
+
return positions;
|
|
6440
|
+
}, [rows, cols, size, gap]);
|
|
6441
|
+
const svgDimensions = React.useMemo(() => {
|
|
6442
|
+
return {
|
|
6443
|
+
width: cols * (size + gap) - gap,
|
|
6444
|
+
height: rows * (size + gap) - gap
|
|
6445
|
+
};
|
|
6446
|
+
}, [rows, cols, size, gap]);
|
|
6447
|
+
const isAnimating = !pattern && frames && frames.length > 0;
|
|
6448
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6449
|
+
"div",
|
|
6450
|
+
{
|
|
6451
|
+
ref,
|
|
6452
|
+
role: "img",
|
|
6453
|
+
"aria-label": ariaLabel ?? "matrix display",
|
|
6454
|
+
"aria-live": isAnimating ? "polite" : void 0,
|
|
6455
|
+
className: cn("relative inline-block", className),
|
|
6456
|
+
style: {
|
|
6457
|
+
"--matrix-on": palette.on,
|
|
6458
|
+
"--matrix-off": palette.off,
|
|
6459
|
+
"--matrix-gap": `${gap}px`,
|
|
6460
|
+
"--matrix-size": `${size}px`
|
|
6461
|
+
},
|
|
6462
|
+
...props,
|
|
6463
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6464
|
+
"svg",
|
|
6465
|
+
{
|
|
6466
|
+
width: svgDimensions.width,
|
|
6467
|
+
height: svgDimensions.height,
|
|
6468
|
+
viewBox: `0 0 ${svgDimensions.width} ${svgDimensions.height}`,
|
|
6469
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6470
|
+
className: "block",
|
|
6471
|
+
style: { overflow: "visible" },
|
|
6472
|
+
children: [
|
|
6473
|
+
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
6474
|
+
/* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: "matrix-pixel-on", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6475
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "var(--matrix-on)", stopOpacity: "1" }),
|
|
6476
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6477
|
+
"stop",
|
|
6478
|
+
{
|
|
6479
|
+
offset: "70%",
|
|
6480
|
+
stopColor: "var(--matrix-on)",
|
|
6481
|
+
stopOpacity: "0.85"
|
|
6482
|
+
}
|
|
6483
|
+
),
|
|
6484
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6485
|
+
"stop",
|
|
6486
|
+
{
|
|
6487
|
+
offset: "100%",
|
|
6488
|
+
stopColor: "var(--matrix-on)",
|
|
6489
|
+
stopOpacity: "0.6"
|
|
6490
|
+
}
|
|
6491
|
+
)
|
|
6492
|
+
] }),
|
|
6493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: "matrix-pixel-off", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6494
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6495
|
+
"stop",
|
|
6496
|
+
{
|
|
6497
|
+
offset: "0%",
|
|
6498
|
+
stopColor: "var(--muted-foreground)",
|
|
6499
|
+
stopOpacity: "1"
|
|
6500
|
+
}
|
|
6501
|
+
),
|
|
6502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6503
|
+
"stop",
|
|
6504
|
+
{
|
|
6505
|
+
offset: "100%",
|
|
6506
|
+
stopColor: "var(--muted-foreground)",
|
|
6507
|
+
stopOpacity: "0.7"
|
|
6508
|
+
}
|
|
6509
|
+
)
|
|
6510
|
+
] }),
|
|
6511
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6512
|
+
"filter",
|
|
6513
|
+
{
|
|
6514
|
+
id: "matrix-glow",
|
|
6515
|
+
x: "-50%",
|
|
6516
|
+
y: "-50%",
|
|
6517
|
+
width: "200%",
|
|
6518
|
+
height: "200%",
|
|
6519
|
+
children: [
|
|
6520
|
+
/* @__PURE__ */ jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "2", result: "blur" }),
|
|
6521
|
+
/* @__PURE__ */ jsxRuntime.jsx("feComposite", { in: "SourceGraphic", in2: "blur", operator: "over" })
|
|
6522
|
+
]
|
|
6523
|
+
}
|
|
6524
|
+
)
|
|
6525
|
+
] }),
|
|
6526
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
6527
|
+
.matrix-pixel {
|
|
6528
|
+
transition: opacity 300ms ease-out, transform 150ms ease-out;
|
|
6529
|
+
transform-origin: center;
|
|
6530
|
+
transform-box: fill-box;
|
|
6531
|
+
}
|
|
6532
|
+
.matrix-pixel-active {
|
|
6533
|
+
filter: url(#matrix-glow);
|
|
6534
|
+
}
|
|
6535
|
+
` }),
|
|
6536
|
+
currentFrame.map(
|
|
6537
|
+
(row, rowIndex) => row.map((value, colIndex) => {
|
|
6538
|
+
const pos = cellPositions[rowIndex]?.[colIndex];
|
|
6539
|
+
if (!pos) return null;
|
|
6540
|
+
const opacity = clamp(brightness * value);
|
|
6541
|
+
const isActive = opacity > 0.5;
|
|
6542
|
+
const isOn = opacity > 0.05;
|
|
6543
|
+
const fill = isOn ? "url(#matrix-pixel-on)" : "url(#matrix-pixel-off)";
|
|
6544
|
+
const scale = isActive ? 1.1 : 1;
|
|
6545
|
+
const radius = size / 2 * 0.9;
|
|
6546
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6547
|
+
"circle",
|
|
6548
|
+
{
|
|
6549
|
+
className: cn(
|
|
6550
|
+
"matrix-pixel",
|
|
6551
|
+
isActive && "matrix-pixel-active",
|
|
6552
|
+
!isOn && "opacity-20 dark:opacity-[0.1]"
|
|
6553
|
+
),
|
|
6554
|
+
cx: pos.x + size / 2,
|
|
6555
|
+
cy: pos.y + size / 2,
|
|
6556
|
+
r: radius,
|
|
6557
|
+
fill,
|
|
6558
|
+
opacity: isOn ? opacity : 0.1,
|
|
6559
|
+
style: {
|
|
6560
|
+
transform: `scale(${scale})`
|
|
6561
|
+
}
|
|
6562
|
+
},
|
|
6563
|
+
`${rowIndex}-${colIndex}`
|
|
6564
|
+
);
|
|
6565
|
+
})
|
|
6566
|
+
)
|
|
6567
|
+
]
|
|
6568
|
+
}
|
|
6569
|
+
)
|
|
6570
|
+
}
|
|
6571
|
+
);
|
|
6572
|
+
}
|
|
6573
|
+
);
|
|
6574
|
+
Matrix.displayName = "Matrix";
|
|
6575
|
+
var DEFAULT_SIZE = 22;
|
|
6576
|
+
var MATRIX_GRID = 7;
|
|
6577
|
+
var MATRIX_ON = "var(--payman-v2-matrix-color)";
|
|
6578
|
+
var MATRIX_PRESETS = [
|
|
6579
|
+
{ frames: loader, fps: 8 },
|
|
6580
|
+
{ frames: wave, fps: 14 },
|
|
6581
|
+
{ frames: snake, fps: 16 },
|
|
6582
|
+
{ frames: pulse, fps: 12 }
|
|
6583
|
+
];
|
|
6584
|
+
var PRESET_ROTATE_MS = 1e4;
|
|
5625
6585
|
function useElapsedSeconds(isStreaming) {
|
|
5626
|
-
const [elapsed, setElapsed] =
|
|
5627
|
-
const startRef =
|
|
5628
|
-
|
|
6586
|
+
const [elapsed, setElapsed] = React.useState(0);
|
|
6587
|
+
const startRef = React.useRef(null);
|
|
6588
|
+
React.useEffect(() => {
|
|
5629
6589
|
if (!isStreaming) {
|
|
5630
6590
|
startRef.current = null;
|
|
5631
6591
|
setElapsed(0);
|
|
@@ -5642,12 +6602,37 @@ function useElapsedSeconds(isStreaming) {
|
|
|
5642
6602
|
}, [isStreaming]);
|
|
5643
6603
|
return elapsed;
|
|
5644
6604
|
}
|
|
6605
|
+
function useMatrixPresetIndex(isStreaming) {
|
|
6606
|
+
const [index, setIndex] = React.useState(0);
|
|
6607
|
+
React.useEffect(() => {
|
|
6608
|
+
if (!isStreaming) return;
|
|
6609
|
+
setIndex(0);
|
|
6610
|
+
const id = setInterval(() => {
|
|
6611
|
+
setIndex((prev) => (prev + 1) % MATRIX_PRESETS.length);
|
|
6612
|
+
}, PRESET_ROTATE_MS);
|
|
6613
|
+
return () => clearInterval(id);
|
|
6614
|
+
}, [isStreaming]);
|
|
6615
|
+
return index;
|
|
6616
|
+
}
|
|
6617
|
+
function formatElapsed(totalSeconds) {
|
|
6618
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
6619
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6620
|
+
const seconds = totalSeconds % 60;
|
|
6621
|
+
return `${minutes}m ${seconds}s`;
|
|
6622
|
+
}
|
|
5645
6623
|
function StreamingIndicatorV2({
|
|
5646
6624
|
isStreaming,
|
|
5647
6625
|
loadingAnimation
|
|
5648
6626
|
}) {
|
|
5649
6627
|
const size = loadingAnimation?.size ?? DEFAULT_SIZE;
|
|
5650
6628
|
const elapsed = useElapsedSeconds(isStreaming);
|
|
6629
|
+
const presetIndex = useMatrixPresetIndex(isStreaming);
|
|
6630
|
+
const preset = MATRIX_PRESETS[presetIndex];
|
|
6631
|
+
const gap = 1;
|
|
6632
|
+
const cell = React.useMemo(
|
|
6633
|
+
() => Math.max(2, Math.round((size - (MATRIX_GRID - 1) * gap) / MATRIX_GRID)),
|
|
6634
|
+
[size]
|
|
6635
|
+
);
|
|
5651
6636
|
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isStreaming && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5652
6637
|
framerMotion.motion.div,
|
|
5653
6638
|
{
|
|
@@ -5663,43 +6648,84 @@ function StreamingIndicatorV2({
|
|
|
5663
6648
|
{
|
|
5664
6649
|
className: "payman-v2-streaming-indicator-glyph",
|
|
5665
6650
|
style: { width: size, height: size },
|
|
5666
|
-
children:
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
6651
|
+
children: loadingAnimation?.src ? (
|
|
6652
|
+
// Consumer override: render their Lottie animation.
|
|
6653
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6654
|
+
dotlottieReact.DotLottieReact,
|
|
6655
|
+
{
|
|
6656
|
+
src: loadingAnimation.src,
|
|
6657
|
+
loop: true,
|
|
6658
|
+
autoplay: true,
|
|
6659
|
+
style: { width: "100%", height: "100%" }
|
|
6660
|
+
}
|
|
6661
|
+
)
|
|
6662
|
+
) : (
|
|
6663
|
+
// Default: dot-matrix glyph, cycling presets +
|
|
6664
|
+
// Payman brand tint. Each preset lives in its own
|
|
6665
|
+
// keyed motion layer so swapping presets crossfades
|
|
6666
|
+
// (old scales/fades out while the new scales/fades
|
|
6667
|
+
// in) instead of hard-cutting. Keying the layer on
|
|
6668
|
+
// `presetIndex` also remounts the Matrix, restarting
|
|
6669
|
+
// its frame counter cleanly at frame 0.
|
|
6670
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6671
|
+
framerMotion.motion.div,
|
|
6672
|
+
{
|
|
6673
|
+
className: "payman-v2-streaming-indicator-matrix",
|
|
6674
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
6675
|
+
animate: { opacity: 1, scale: 1 },
|
|
6676
|
+
exit: { opacity: 0, scale: 0.8 },
|
|
6677
|
+
transition: { duration: 0.45, ease: [0.2, 0, 0, 1] },
|
|
6678
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6679
|
+
Matrix,
|
|
6680
|
+
{
|
|
6681
|
+
rows: MATRIX_GRID,
|
|
6682
|
+
cols: MATRIX_GRID,
|
|
6683
|
+
frames: preset.frames,
|
|
6684
|
+
fps: preset.fps,
|
|
6685
|
+
size: cell,
|
|
6686
|
+
gap,
|
|
6687
|
+
palette: {
|
|
6688
|
+
on: MATRIX_ON,
|
|
6689
|
+
// Unlit dots use the v2 theme's own muted-text
|
|
6690
|
+
// token (light/dark-aware), not the bare
|
|
6691
|
+
// `--muted-foreground` the vendored Matrix
|
|
6692
|
+
// component falls back to internally — that
|
|
6693
|
+
// variable isn't defined under `.payman-v2-root`
|
|
6694
|
+
// and would otherwise resolve to black.
|
|
6695
|
+
off: "var(--payman-v2-matrix-dot-off)"
|
|
6696
|
+
},
|
|
6697
|
+
ariaLabel: "Working\u2026"
|
|
6698
|
+
}
|
|
6699
|
+
)
|
|
6700
|
+
},
|
|
6701
|
+
presetIndex
|
|
6702
|
+
) })
|
|
5674
6703
|
)
|
|
5675
6704
|
}
|
|
5676
6705
|
),
|
|
5677
|
-
elapsed > 0 && /* @__PURE__ */ jsxRuntime.
|
|
5678
|
-
elapsed,
|
|
5679
|
-
"s"
|
|
5680
|
-
] })
|
|
6706
|
+
elapsed > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-streaming-indicator-elapsed", children: formatElapsed(elapsed) })
|
|
5681
6707
|
]
|
|
5682
6708
|
},
|
|
5683
6709
|
"streaming-indicator"
|
|
5684
6710
|
) });
|
|
5685
6711
|
}
|
|
5686
6712
|
function ImageLightboxV2({ src, alt, onClose }) {
|
|
5687
|
-
const [isMounted, setIsMounted] =
|
|
5688
|
-
const [isImageLoaded, setIsImageLoaded] =
|
|
5689
|
-
|
|
6713
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
6714
|
+
const [isImageLoaded, setIsImageLoaded] = React.useState(false);
|
|
6715
|
+
React.useEffect(() => {
|
|
5690
6716
|
setIsMounted(true);
|
|
5691
6717
|
return () => setIsMounted(false);
|
|
5692
6718
|
}, []);
|
|
5693
|
-
|
|
6719
|
+
React.useEffect(() => {
|
|
5694
6720
|
setIsImageLoaded(false);
|
|
5695
6721
|
}, [src]);
|
|
5696
|
-
const handleKeyDown =
|
|
6722
|
+
const handleKeyDown = React.useCallback(
|
|
5697
6723
|
(e) => {
|
|
5698
6724
|
if (e.key === "Escape") onClose();
|
|
5699
6725
|
},
|
|
5700
6726
|
[onClose]
|
|
5701
6727
|
);
|
|
5702
|
-
|
|
6728
|
+
React.useEffect(() => {
|
|
5703
6729
|
if (!src || typeof document === "undefined") return;
|
|
5704
6730
|
document.addEventListener("keydown", handleKeyDown);
|
|
5705
6731
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -5848,10 +6874,10 @@ function TraceTimelineModal({
|
|
|
5848
6874
|
apiBaseUrl,
|
|
5849
6875
|
apiHeaders
|
|
5850
6876
|
}) {
|
|
5851
|
-
const [trace, setTrace] =
|
|
5852
|
-
const [loading, setLoading] =
|
|
5853
|
-
const [error, setError] =
|
|
5854
|
-
|
|
6877
|
+
const [trace, setTrace] = React.useState(null);
|
|
6878
|
+
const [loading, setLoading] = React.useState(false);
|
|
6879
|
+
const [error, setError] = React.useState(null);
|
|
6880
|
+
React.useEffect(() => {
|
|
5855
6881
|
if (!open || !executionId) return;
|
|
5856
6882
|
const ctrl = new AbortController();
|
|
5857
6883
|
setLoading(true);
|
|
@@ -5873,7 +6899,7 @@ function TraceTimelineModal({
|
|
|
5873
6899
|
}).finally(() => setLoading(false));
|
|
5874
6900
|
return () => ctrl.abort();
|
|
5875
6901
|
}, [open, executionId, apiBaseUrl, apiHeaders]);
|
|
5876
|
-
const totalMs =
|
|
6902
|
+
const totalMs = React.useMemo(() => {
|
|
5877
6903
|
if (!trace) return 0;
|
|
5878
6904
|
const meta = trace.runMetadata?.totalTimeMs;
|
|
5879
6905
|
if (typeof meta === "number" && meta > 0) return meta;
|
|
@@ -5882,7 +6908,7 @@ function TraceTimelineModal({
|
|
|
5882
6908
|
if (starts.length === 0 || ends.length === 0) return 0;
|
|
5883
6909
|
return Math.max(...ends) - Math.min(...starts);
|
|
5884
6910
|
}, [trace]);
|
|
5885
|
-
const accountedMs =
|
|
6911
|
+
const accountedMs = React.useMemo(
|
|
5886
6912
|
() => (trace?.pipelineSteps ?? []).reduce(
|
|
5887
6913
|
(sum, s) => sum + (s.durationMs ?? 0),
|
|
5888
6914
|
0
|
|
@@ -6143,12 +7169,12 @@ var NOOP_ASYNC = async () => {
|
|
|
6143
7169
|
var NOOP = () => {
|
|
6144
7170
|
};
|
|
6145
7171
|
function useSentryChatCallbacks(callbacks, config) {
|
|
6146
|
-
const sentryCtxRef =
|
|
6147
|
-
const callbacksRef =
|
|
7172
|
+
const sentryCtxRef = React.useRef({});
|
|
7173
|
+
const callbacksRef = React.useRef(callbacks);
|
|
6148
7174
|
callbacksRef.current = callbacks;
|
|
6149
7175
|
const initialSessionId = config.initialSessionId;
|
|
6150
7176
|
const apiHeaders = config.api.headers;
|
|
6151
|
-
|
|
7177
|
+
React.useEffect(() => {
|
|
6152
7178
|
sentryCtxRef.current.agentId = config.agentId;
|
|
6153
7179
|
sentryCtxRef.current.sessionOwnerId = config.sessionParams?.id;
|
|
6154
7180
|
if (initialSessionId) {
|
|
@@ -6164,13 +7190,13 @@ function useSentryChatCallbacks(callbacks, config) {
|
|
|
6164
7190
|
initialSessionId,
|
|
6165
7191
|
apiHeaders
|
|
6166
7192
|
]);
|
|
6167
|
-
|
|
7193
|
+
React.useEffect(() => {
|
|
6168
7194
|
const endpoint = config.api.streamEndpoint || "/api/playground/ask/stream";
|
|
6169
7195
|
return subscribeToCfRay(endpoint, (cfRay) => {
|
|
6170
7196
|
sentryCtxRef.current.cfRay = cfRay;
|
|
6171
7197
|
});
|
|
6172
7198
|
}, [config.api.streamEndpoint]);
|
|
6173
|
-
return
|
|
7199
|
+
return React.useMemo(
|
|
6174
7200
|
() => ({
|
|
6175
7201
|
onMessageSent: (msg) => callbacksRef.current?.onMessageSent?.(msg),
|
|
6176
7202
|
onStreamStart: () => callbacksRef.current?.onStreamStart?.(),
|
|
@@ -6219,7 +7245,7 @@ function useSentryChatCallbacks(callbacks, config) {
|
|
|
6219
7245
|
[]
|
|
6220
7246
|
);
|
|
6221
7247
|
}
|
|
6222
|
-
var PaymanChatInner =
|
|
7248
|
+
var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
6223
7249
|
config,
|
|
6224
7250
|
callbacks = {},
|
|
6225
7251
|
className,
|
|
@@ -6230,18 +7256,18 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6230
7256
|
hasMoreMessages = false,
|
|
6231
7257
|
chat
|
|
6232
7258
|
}, ref) {
|
|
6233
|
-
const [inputValue, setInputValue] =
|
|
6234
|
-
const prevInputValueRef =
|
|
6235
|
-
const [hasEverSentMessage, setHasEverSentMessage] =
|
|
6236
|
-
const [lightboxSrc, setLightboxSrc] =
|
|
6237
|
-
const [lightboxAlt, setLightboxAlt] =
|
|
6238
|
-
const [editingMessageId, setEditingMessageId] =
|
|
6239
|
-
const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] =
|
|
6240
|
-
const [analysisMode, setAnalysisMode] =
|
|
6241
|
-
const chatInputV2Ref =
|
|
6242
|
-
const messageListV2Ref =
|
|
6243
|
-
const resetToEmptyStateRef =
|
|
6244
|
-
|
|
7259
|
+
const [inputValue, setInputValue] = React.useState("");
|
|
7260
|
+
const prevInputValueRef = React.useRef(inputValue);
|
|
7261
|
+
const [hasEverSentMessage, setHasEverSentMessage] = React.useState(false);
|
|
7262
|
+
const [lightboxSrc, setLightboxSrc] = React.useState(null);
|
|
7263
|
+
const [lightboxAlt, setLightboxAlt] = React.useState("");
|
|
7264
|
+
const [editingMessageId, setEditingMessageId] = React.useState(null);
|
|
7265
|
+
const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] = React.useState(false);
|
|
7266
|
+
const [analysisMode, setAnalysisMode] = React.useState("fast");
|
|
7267
|
+
const chatInputV2Ref = React.useRef(null);
|
|
7268
|
+
const messageListV2Ref = React.useRef(null);
|
|
7269
|
+
const resetToEmptyStateRef = React.useRef(false);
|
|
7270
|
+
React.useEffect(() => {
|
|
6245
7271
|
if (config.sentryDsn) {
|
|
6246
7272
|
initSentryIfNeeded(config.sentryDsn);
|
|
6247
7273
|
}
|
|
@@ -6257,7 +7283,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6257
7283
|
getSessionId,
|
|
6258
7284
|
getMessages
|
|
6259
7285
|
} = chat;
|
|
6260
|
-
|
|
7286
|
+
React.useEffect(() => {
|
|
6261
7287
|
if (resetToEmptyStateRef.current) {
|
|
6262
7288
|
if (messages.length === 0) {
|
|
6263
7289
|
setHasEverSentMessage(false);
|
|
@@ -6269,7 +7295,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6269
7295
|
setHasEverSentMessage(true);
|
|
6270
7296
|
}
|
|
6271
7297
|
}, [messages.length, hasEverSentMessage]);
|
|
6272
|
-
|
|
7298
|
+
React.useEffect(() => {
|
|
6273
7299
|
if (!editingMessageId) return;
|
|
6274
7300
|
const editingMessageStillExists = messages.some(
|
|
6275
7301
|
(message) => message.id === editingMessageId && message.role === "user"
|
|
@@ -6285,6 +7311,15 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6285
7311
|
const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
|
|
6286
7312
|
const dismissNotification = chat.dismissNotification ?? NOOP;
|
|
6287
7313
|
const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
|
|
7314
|
+
const expiredUserActionIdsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
7315
|
+
const expireUserActionOnce = React.useCallback(
|
|
7316
|
+
(userActionId) => {
|
|
7317
|
+
if (expiredUserActionIdsRef.current.has(userActionId)) return;
|
|
7318
|
+
expiredUserActionIdsRef.current.add(userActionId);
|
|
7319
|
+
void expireUserAction2(userActionId);
|
|
7320
|
+
},
|
|
7321
|
+
[expireUserAction2]
|
|
7322
|
+
);
|
|
6288
7323
|
const {
|
|
6289
7324
|
transcribedText,
|
|
6290
7325
|
isAvailable: voiceAvailable,
|
|
@@ -6308,7 +7343,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6308
7343
|
}
|
|
6309
7344
|
}
|
|
6310
7345
|
);
|
|
6311
|
-
const contextValue =
|
|
7346
|
+
const contextValue = React.useMemo(
|
|
6312
7347
|
() => ({
|
|
6313
7348
|
resetSession,
|
|
6314
7349
|
clearMessages,
|
|
@@ -6335,8 +7370,8 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6335
7370
|
onAttachFileClick,
|
|
6336
7371
|
onMessageFeedback
|
|
6337
7372
|
} = callbacks;
|
|
6338
|
-
const [debugTraceExecutionId, setDebugTraceExecutionId] =
|
|
6339
|
-
const handleSubmitFeedback =
|
|
7373
|
+
const [debugTraceExecutionId, setDebugTraceExecutionId] = React.useState(null);
|
|
7374
|
+
const handleSubmitFeedback = React.useCallback(
|
|
6340
7375
|
async ({ messageId, executionId, feedback, details }) => {
|
|
6341
7376
|
if (!executionId) {
|
|
6342
7377
|
throw new Error("Cannot submit feedback before the response completes");
|
|
@@ -6367,14 +7402,14 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6367
7402
|
onMessageFeedback
|
|
6368
7403
|
]
|
|
6369
7404
|
);
|
|
6370
|
-
const onExecutionTraceClick =
|
|
7405
|
+
const onExecutionTraceClick = React.useMemo(() => {
|
|
6371
7406
|
if (!config.debug) return rawOnExecutionTraceClick;
|
|
6372
7407
|
return (data) => {
|
|
6373
7408
|
rawOnExecutionTraceClick?.(data);
|
|
6374
7409
|
if (data.executionId) setDebugTraceExecutionId(data.executionId);
|
|
6375
7410
|
};
|
|
6376
7411
|
}, [config.debug, rawOnExecutionTraceClick]);
|
|
6377
|
-
const performResetSession =
|
|
7412
|
+
const performResetSession = React.useCallback(() => {
|
|
6378
7413
|
resetToEmptyStateRef.current = true;
|
|
6379
7414
|
setEditingMessageId(null);
|
|
6380
7415
|
setIsResetSessionConfirmOpen(false);
|
|
@@ -6395,13 +7430,13 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6395
7430
|
resetSession,
|
|
6396
7431
|
stopRecording
|
|
6397
7432
|
]);
|
|
6398
|
-
const requestResetSession =
|
|
7433
|
+
const requestResetSession = React.useCallback(() => {
|
|
6399
7434
|
setIsResetSessionConfirmOpen(true);
|
|
6400
7435
|
}, []);
|
|
6401
|
-
const closeResetSessionConfirm =
|
|
7436
|
+
const closeResetSessionConfirm = React.useCallback(() => {
|
|
6402
7437
|
setIsResetSessionConfirmOpen(false);
|
|
6403
7438
|
}, []);
|
|
6404
|
-
|
|
7439
|
+
React.useImperativeHandle(ref, () => ({
|
|
6405
7440
|
resetSession: performResetSession,
|
|
6406
7441
|
clearMessages,
|
|
6407
7442
|
cancelStream,
|
|
@@ -6440,7 +7475,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6440
7475
|
slashCommands: slashCommandsConfig,
|
|
6441
7476
|
commandPermissions
|
|
6442
7477
|
} = config;
|
|
6443
|
-
const messageActions =
|
|
7478
|
+
const messageActions = React.useMemo(
|
|
6444
7479
|
() => ({
|
|
6445
7480
|
userMessageActions: {
|
|
6446
7481
|
copy: messageActionsConfig?.userMessageActions?.copy ?? true,
|
|
@@ -6456,18 +7491,18 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6456
7491
|
}),
|
|
6457
7492
|
[messageActionsConfig]
|
|
6458
7493
|
);
|
|
6459
|
-
const slashCommands =
|
|
7494
|
+
const slashCommands = React.useMemo(
|
|
6460
7495
|
() => enableSlashCommands ? filterSlashCommands(
|
|
6461
7496
|
slashCommandsConfig ?? DEFAULT_SLASH_COMMANDS,
|
|
6462
7497
|
commandPermissions
|
|
6463
7498
|
) : [],
|
|
6464
7499
|
[commandPermissions, enableSlashCommands, slashCommandsConfig]
|
|
6465
7500
|
);
|
|
6466
|
-
const isSessionParamsConfigured =
|
|
7501
|
+
const isSessionParamsConfigured = React.useMemo(() => {
|
|
6467
7502
|
if (!sessionParams) return false;
|
|
6468
7503
|
return !!(sessionParams.id?.trim() && sessionParams.name?.trim());
|
|
6469
7504
|
}, [sessionParams?.id, sessionParams?.name]);
|
|
6470
|
-
|
|
7505
|
+
React.useEffect(() => {
|
|
6471
7506
|
const wasEmpty = prevInputValueRef.current.trim() === "";
|
|
6472
7507
|
const isEmpty2 = inputValue.trim() === "";
|
|
6473
7508
|
prevInputValueRef.current = inputValue;
|
|
@@ -6527,6 +7562,9 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6527
7562
|
};
|
|
6528
7563
|
const userActionPrompts = isUserActionSupported ? userActionState.prompts : void 0;
|
|
6529
7564
|
const notifications = userActionState.notifications;
|
|
7565
|
+
const dockedPrompt = userActionPrompts?.find(
|
|
7566
|
+
(prompt) => prompt.kind !== "notification" && (prompt.status === "pending" || prompt.status === "submitting" || prompt.status === "stale")
|
|
7567
|
+
);
|
|
6530
7568
|
const handleV2Send = (text) => {
|
|
6531
7569
|
if (isRecording) stopRecording();
|
|
6532
7570
|
if (text.trim() && !disableInput && isSessionParamsConfigured) {
|
|
@@ -6534,7 +7572,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6534
7572
|
void sendMessage(text.trim(), { analysisMode: effectiveAnalysisMode });
|
|
6535
7573
|
}
|
|
6536
7574
|
};
|
|
6537
|
-
const handleVoicePress =
|
|
7575
|
+
const handleVoicePress = React.useCallback(async () => {
|
|
6538
7576
|
if (!voiceAvailable) return;
|
|
6539
7577
|
if (isRecording) {
|
|
6540
7578
|
stopRecording();
|
|
@@ -6543,7 +7581,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6543
7581
|
clearTranscript();
|
|
6544
7582
|
await startRecording();
|
|
6545
7583
|
}, [clearTranscript, isRecording, startRecording, stopRecording, voiceAvailable]);
|
|
6546
|
-
const handleEditMessageDraft =
|
|
7584
|
+
const handleEditMessageDraft = React.useCallback((messageId) => {
|
|
6547
7585
|
const targetMessage = messages.find((message) => message.id === messageId);
|
|
6548
7586
|
if (!targetMessage?.content.trim()) return;
|
|
6549
7587
|
setEditingMessageId(messageId);
|
|
@@ -6552,7 +7590,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6552
7590
|
messageListV2Ref.current?.scrollToBottom("smooth");
|
|
6553
7591
|
});
|
|
6554
7592
|
}, [messages]);
|
|
6555
|
-
const handleRetryUserMessage =
|
|
7593
|
+
const handleRetryUserMessage = React.useCallback((messageId) => {
|
|
6556
7594
|
if (isWaitingForResponse) return;
|
|
6557
7595
|
const targetMessage = messages.find(
|
|
6558
7596
|
(message) => message.id === messageId && message.role === "user"
|
|
@@ -6569,7 +7607,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6569
7607
|
});
|
|
6570
7608
|
});
|
|
6571
7609
|
}, [isWaitingForResponse, messages, sendMessage, effectiveAnalysisMode]);
|
|
6572
|
-
const handleClearEditing =
|
|
7610
|
+
const handleClearEditing = React.useCallback(() => {
|
|
6573
7611
|
setEditingMessageId(null);
|
|
6574
7612
|
}, []);
|
|
6575
7613
|
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6679,11 +7717,12 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6679
7717
|
retryDisabled: isWaitingForResponse,
|
|
6680
7718
|
typingSpeed: config.typingSpeed ?? 4,
|
|
6681
7719
|
userActionPrompts,
|
|
7720
|
+
dockedUserActionId: dockedPrompt?.userActionId,
|
|
6682
7721
|
notifications,
|
|
6683
7722
|
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
6684
7723
|
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
6685
7724
|
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
6686
|
-
onExpireUserAction: isUserActionSupported ?
|
|
7725
|
+
onExpireUserAction: isUserActionSupported ? async (id) => expireUserActionOnce(id) : void 0,
|
|
6687
7726
|
onDismissNotification: dismissNotification,
|
|
6688
7727
|
onSubmitFeedback: handleSubmitFeedback
|
|
6689
7728
|
}
|
|
@@ -6696,33 +7735,43 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6696
7735
|
}
|
|
6697
7736
|
),
|
|
6698
7737
|
hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6699
|
-
|
|
7738
|
+
UserActionDock,
|
|
6700
7739
|
{
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
onCancel:
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
7740
|
+
prompt: isUserActionSupported ? dockedPrompt : void 0,
|
|
7741
|
+
onSubmit: submitUserAction2,
|
|
7742
|
+
onCancel: cancelUserAction2,
|
|
7743
|
+
onResend: resendUserAction2,
|
|
7744
|
+
onExpired: expireUserActionOnce,
|
|
7745
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7746
|
+
ChatInputV2,
|
|
7747
|
+
{
|
|
7748
|
+
ref: chatInputV2Ref,
|
|
7749
|
+
onSend: handleV2Send,
|
|
7750
|
+
onCancel: cancelStream,
|
|
7751
|
+
disabled: isV2InputDisabled,
|
|
7752
|
+
isStreaming: isWaitingForResponse,
|
|
7753
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
7754
|
+
enableVoice: config.enableVoice === true,
|
|
7755
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
7756
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
7757
|
+
isRecording,
|
|
7758
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
7759
|
+
onCancelRecording: handleCancelRecording,
|
|
7760
|
+
onConfirmRecording: handleConfirmRecording,
|
|
7761
|
+
showResetSession,
|
|
7762
|
+
onResetSession: requestResetSession,
|
|
7763
|
+
showAttachmentButton,
|
|
7764
|
+
showUploadImageButton,
|
|
7765
|
+
showAttachFileButton,
|
|
7766
|
+
onUploadImageClick,
|
|
7767
|
+
onAttachFileClick,
|
|
7768
|
+
editingMessageId,
|
|
7769
|
+
onClearEditing: handleClearEditing,
|
|
7770
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
7771
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
7772
|
+
slashCommands
|
|
7773
|
+
}
|
|
7774
|
+
)
|
|
6726
7775
|
}
|
|
6727
7776
|
)
|
|
6728
7777
|
]
|
|
@@ -6759,7 +7808,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6759
7808
|
}
|
|
6760
7809
|
) });
|
|
6761
7810
|
});
|
|
6762
|
-
var PaymanChat =
|
|
7811
|
+
var PaymanChat = React.forwardRef(
|
|
6763
7812
|
function PaymanChat2(props, ref) {
|
|
6764
7813
|
const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
|
|
6765
7814
|
const chat = useChatV2(props.config, mergedCallbacks);
|