@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.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import { createContext, forwardRef, useCallback, useRef, useState, useMemo, useEffect, useImperativeHandle, useLayoutEffect, useContext } from 'react';
|
|
2
|
-
import { AnimatePresence, motion } from 'framer-motion';
|
|
3
|
+
import { AnimatePresence, motion, useMotionValue, useSpring, useInView } from 'framer-motion';
|
|
3
4
|
import { clsx } from 'clsx';
|
|
4
5
|
import { twMerge } from 'tailwind-merge';
|
|
5
6
|
import * as Sentry from '@sentry/react';
|
|
@@ -273,6 +274,8 @@ function getEventMessage(event) {
|
|
|
273
274
|
}
|
|
274
275
|
case "RUN_IN_PROGRESS":
|
|
275
276
|
return event.partialText || "Thinking...";
|
|
277
|
+
case "LLM_CALL_STARTED":
|
|
278
|
+
return event.description || "";
|
|
276
279
|
case "RUN_COMPLETED":
|
|
277
280
|
return "Agent run completed";
|
|
278
281
|
case "RUN_FAILED":
|
|
@@ -410,7 +413,8 @@ function createInitialV2State() {
|
|
|
410
413
|
finalData: void 0,
|
|
411
414
|
steps: [],
|
|
412
415
|
stepCounter: 0,
|
|
413
|
-
currentExecutingStepId: void 0
|
|
416
|
+
currentExecutingStepId: void 0,
|
|
417
|
+
trailingActivity: false
|
|
414
418
|
};
|
|
415
419
|
}
|
|
416
420
|
function upsertUserAction(state, req) {
|
|
@@ -432,6 +436,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
432
436
|
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
433
437
|
if (event.executionId) state.executionId = event.executionId;
|
|
434
438
|
if (event.sessionId) state.sessionId = event.sessionId;
|
|
439
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
435
440
|
const description = typeof event.description === "string" ? event.description : "";
|
|
436
441
|
if (description) {
|
|
437
442
|
for (let i = state.steps.length - 1; i >= 0; i--) {
|
|
@@ -466,7 +471,12 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
466
471
|
state.lastEventType = eventType;
|
|
467
472
|
break;
|
|
468
473
|
}
|
|
474
|
+
case "LLM_CALL_STARTED":
|
|
475
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
476
|
+
state.lastEventType = eventType;
|
|
477
|
+
break;
|
|
469
478
|
case "INTENT_STARTED": {
|
|
479
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
470
480
|
const stepId = `step-${state.stepCounter++}`;
|
|
471
481
|
state.steps.push({
|
|
472
482
|
id: stepId,
|
|
@@ -482,6 +492,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
482
492
|
break;
|
|
483
493
|
}
|
|
484
494
|
case "INTENT_COMPLETED": {
|
|
495
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
485
496
|
const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
|
|
486
497
|
if (intentStep) {
|
|
487
498
|
intentStep.status = "completed";
|
|
@@ -513,6 +524,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
513
524
|
step2.status = "completed";
|
|
514
525
|
}
|
|
515
526
|
});
|
|
527
|
+
state.trailingActivity = false;
|
|
516
528
|
state.lastEventType = eventType;
|
|
517
529
|
break;
|
|
518
530
|
}
|
|
@@ -584,6 +596,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
584
596
|
case "WORKFLOW_ERROR":
|
|
585
597
|
state.hasError = true;
|
|
586
598
|
state.errorMessage = event.errorMessage || event.message || "Workflow error";
|
|
599
|
+
state.trailingActivity = false;
|
|
587
600
|
state.lastEventType = eventType;
|
|
588
601
|
break;
|
|
589
602
|
// ---- K2 pipeline stage lifecycle events ----
|
|
@@ -872,7 +885,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
872
885
|
const latestUsefulStep = [...state.steps].reverse().find(
|
|
873
886
|
(s) => s.message && !isBlandStatus(s.message)
|
|
874
887
|
);
|
|
875
|
-
const
|
|
888
|
+
const eventTypeUpper = typeof event.eventType === "string" ? event.eventType.toUpperCase() : "";
|
|
889
|
+
const liveEventLabel = eventTypeUpper === "KEEP_ALIVE" || eventTypeUpper === "LLM_CALL_STARTED" ? useful(getEventMessage(event)) : void 0;
|
|
890
|
+
const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? liveEventLabel ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
|
|
876
891
|
// nothing useful seen yet). Render the bland label so the
|
|
877
892
|
// bubble isn't blank.
|
|
878
893
|
activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
|
|
@@ -897,6 +912,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
897
912
|
streamingContent: state.finalResponse,
|
|
898
913
|
content: "",
|
|
899
914
|
currentMessage,
|
|
915
|
+
hasTrailingActivity: state.trailingActivity,
|
|
900
916
|
streamProgress: "processing",
|
|
901
917
|
isError: false,
|
|
902
918
|
steps: [...state.steps],
|
|
@@ -1112,6 +1128,9 @@ function getUserActionSecondsLeft(prompt) {
|
|
|
1112
1128
|
return void 0;
|
|
1113
1129
|
}
|
|
1114
1130
|
var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
|
|
1131
|
+
function promptSlotKey(p) {
|
|
1132
|
+
return p.toolCallId || p.userActionId;
|
|
1133
|
+
}
|
|
1115
1134
|
function upsertPrompt(prompts, req) {
|
|
1116
1135
|
const idx = prompts.findIndex(
|
|
1117
1136
|
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
@@ -1158,6 +1177,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1158
1177
|
configRef.current = config;
|
|
1159
1178
|
const messagesRef = useRef(messages);
|
|
1160
1179
|
messagesRef.current = messages;
|
|
1180
|
+
const pendingSubmissionsRef = useRef(/* @__PURE__ */ new Map());
|
|
1161
1181
|
const storeAwareSetMessages = useCallback(
|
|
1162
1182
|
(updater) => {
|
|
1163
1183
|
const streamUserId = streamUserIdRef.current;
|
|
@@ -1192,6 +1212,8 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1192
1212
|
if (!config.userId) return EMPTY_USER_ACTION_STATE2;
|
|
1193
1213
|
return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
|
|
1194
1214
|
});
|
|
1215
|
+
const userActionStateRef = useRef(userActionState);
|
|
1216
|
+
userActionStateRef.current = userActionState;
|
|
1195
1217
|
const storeAwareSetUserActionState = useCallback(
|
|
1196
1218
|
(updater) => {
|
|
1197
1219
|
const streamUserId = streamUserIdRef.current;
|
|
@@ -1219,6 +1241,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1219
1241
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1220
1242
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1221
1243
|
onUserActionRequired: (request) => {
|
|
1244
|
+
const requestSlotKey = promptSlotKey(request);
|
|
1245
|
+
for (const [pendingId, slotKey] of pendingSubmissionsRef.current) {
|
|
1246
|
+
if (slotKey === requestSlotKey) {
|
|
1247
|
+
pendingSubmissionsRef.current.delete(pendingId);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1222
1250
|
storeAwareSetUserActionState((prev) => ({
|
|
1223
1251
|
...prev,
|
|
1224
1252
|
prompts: upsertPrompt(prev.prompts, request)
|
|
@@ -1230,6 +1258,28 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1230
1258
|
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1231
1259
|
);
|
|
1232
1260
|
callbacksRef.current.onUserNotification?.(notification);
|
|
1261
|
+
},
|
|
1262
|
+
// A submitted-but-unconfirmed prompt (see `submitUserAction`) is only
|
|
1263
|
+
// safe to drop once the stream has demonstrably moved on. `onEvent`
|
|
1264
|
+
// in useStreamManagerV2 calls `onStepsUpdate` for *every* processed
|
|
1265
|
+
// stream event, unconditionally — so the first time this fires
|
|
1266
|
+
// after a submission, the event in hand is either the rejection
|
|
1267
|
+
// retry (a fresh `USER_ACTION_REQUIRED`, which the handler above
|
|
1268
|
+
// already deleted this pending entry for, earlier in the very same
|
|
1269
|
+
// event) or genuine forward progress (RUN_IN_PROGRESS, a tool call,
|
|
1270
|
+
// content deltas, RUN_COMPLETED, ...). Anything still pending by
|
|
1271
|
+
// the time we get here therefore means the run resumed normally —
|
|
1272
|
+
// clear it.
|
|
1273
|
+
onStepsUpdate: (steps) => {
|
|
1274
|
+
if (pendingSubmissionsRef.current.size > 0) {
|
|
1275
|
+
const resolved = [...pendingSubmissionsRef.current.keys()];
|
|
1276
|
+
pendingSubmissionsRef.current.clear();
|
|
1277
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1278
|
+
...prev,
|
|
1279
|
+
prompts: prev.prompts.filter((p) => !resolved.includes(p.userActionId))
|
|
1280
|
+
}));
|
|
1281
|
+
}
|
|
1282
|
+
callbacksRef.current.onStepsUpdate?.(steps);
|
|
1233
1283
|
}
|
|
1234
1284
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1235
1285
|
}), []);
|
|
@@ -1365,6 +1415,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1365
1415
|
[storeAwareSetUserActionState]
|
|
1366
1416
|
);
|
|
1367
1417
|
const removePrompt = useCallback((userActionId) => {
|
|
1418
|
+
pendingSubmissionsRef.current.delete(userActionId);
|
|
1368
1419
|
storeAwareSetUserActionState((prev) => ({
|
|
1369
1420
|
...prev,
|
|
1370
1421
|
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
@@ -1375,7 +1426,10 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1375
1426
|
setPromptStatus(userActionId, "submitting");
|
|
1376
1427
|
try {
|
|
1377
1428
|
await submitUserAction(configRef.current, userActionId, content);
|
|
1378
|
-
|
|
1429
|
+
const prompt = userActionStateRef.current.prompts.find(
|
|
1430
|
+
(p) => p.userActionId === userActionId
|
|
1431
|
+
);
|
|
1432
|
+
pendingSubmissionsRef.current.set(userActionId, prompt ? promptSlotKey(prompt) : userActionId);
|
|
1379
1433
|
} catch (error) {
|
|
1380
1434
|
if (error instanceof UserActionStaleError) {
|
|
1381
1435
|
setPromptStatus(userActionId, "stale");
|
|
@@ -1386,7 +1440,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1386
1440
|
throw error;
|
|
1387
1441
|
}
|
|
1388
1442
|
},
|
|
1389
|
-
[
|
|
1443
|
+
[setPromptStatus]
|
|
1390
1444
|
);
|
|
1391
1445
|
const cancelUserAction2 = useCallback(
|
|
1392
1446
|
async (userActionId) => {
|
|
@@ -2055,6 +2109,9 @@ function getConflictErrorMessage(errorDetails) {
|
|
|
2055
2109
|
}
|
|
2056
2110
|
function initSentryIfNeeded(dsn) {
|
|
2057
2111
|
if (!dsn) return;
|
|
2112
|
+
if (typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")) {
|
|
2113
|
+
return;
|
|
2114
|
+
}
|
|
2058
2115
|
if (Sentry.getClient()) return;
|
|
2059
2116
|
Sentry.init({
|
|
2060
2117
|
dsn,
|
|
@@ -3436,9 +3493,88 @@ function MarkdownImageV2({
|
|
|
3436
3493
|
}
|
|
3437
3494
|
) });
|
|
3438
3495
|
}
|
|
3439
|
-
|
|
3496
|
+
var RAG_SOURCE_CLASS = "payman-v2-rag-source";
|
|
3497
|
+
var RAG_FOLLOW_UP_CLASS = "payman-v2-rag-follow-up";
|
|
3498
|
+
var SOURCE_PATTERN = /^Sources?:\s*\S/i;
|
|
3499
|
+
var MAX_FOLLOW_UP_LENGTH = 320;
|
|
3500
|
+
var HR_PATTERN = /^-{3,}$|^_{3,}$|^\*{3,}$/;
|
|
3501
|
+
function normalizeRagParagraphText(text) {
|
|
3502
|
+
return text.replace(/\s+/g, " ").trim();
|
|
3503
|
+
}
|
|
3504
|
+
function isRagSourceParagraph(text) {
|
|
3505
|
+
return SOURCE_PATTERN.test(normalizeRagParagraphText(text));
|
|
3506
|
+
}
|
|
3507
|
+
function isRagFollowUpCandidate(text) {
|
|
3508
|
+
const normalized = normalizeRagParagraphText(text);
|
|
3509
|
+
return normalized.length > 0 && normalized.length <= MAX_FOLLOW_UP_LENGTH && normalized.endsWith("?");
|
|
3510
|
+
}
|
|
3511
|
+
function extractRagParagraphTexts(content) {
|
|
3512
|
+
const paragraphs = [];
|
|
3513
|
+
const currentParagraph = [];
|
|
3514
|
+
const flushParagraph = () => {
|
|
3515
|
+
const paragraph = normalizeRagParagraphText(currentParagraph.join(" "));
|
|
3516
|
+
currentParagraph.length = 0;
|
|
3517
|
+
if (paragraph) paragraphs.push(paragraph);
|
|
3518
|
+
};
|
|
3519
|
+
content.replace(/\\n/g, "\n").split(/\r?\n/).forEach((line) => {
|
|
3520
|
+
const trimmedLine = line.trim();
|
|
3521
|
+
if (!trimmedLine) {
|
|
3522
|
+
flushParagraph();
|
|
3523
|
+
return;
|
|
3524
|
+
}
|
|
3525
|
+
if (HR_PATTERN.test(trimmedLine)) {
|
|
3526
|
+
flushParagraph();
|
|
3527
|
+
return;
|
|
3528
|
+
}
|
|
3529
|
+
currentParagraph.push(trimmedLine);
|
|
3530
|
+
});
|
|
3531
|
+
flushParagraph();
|
|
3532
|
+
return paragraphs;
|
|
3533
|
+
}
|
|
3534
|
+
function getRagAnswerParagraphRoles(paragraphs) {
|
|
3535
|
+
const normalized = paragraphs.map(normalizeRagParagraphText);
|
|
3536
|
+
const roles = normalized.map(() => null);
|
|
3537
|
+
const sourceIndexes = normalized.map((paragraph, index) => isRagSourceParagraph(paragraph) ? index : -1).filter((index) => index >= 0);
|
|
3538
|
+
for (const sourceIndex of sourceIndexes) {
|
|
3539
|
+
roles[sourceIndex] = "source";
|
|
3540
|
+
for (const candidateIndex of [sourceIndex - 1, sourceIndex + 1]) {
|
|
3541
|
+
if (candidateIndex >= 0 && candidateIndex < normalized.length && roles[candidateIndex] == null && isRagFollowUpCandidate(normalized[candidateIndex] ?? "")) {
|
|
3542
|
+
roles[candidateIndex] = "follow-up";
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
return roles;
|
|
3547
|
+
}
|
|
3548
|
+
function getRagAnswerParagraphRole(paragraph, paragraphs) {
|
|
3549
|
+
const normalizedParagraph = normalizeRagParagraphText(paragraph);
|
|
3550
|
+
if (isRagSourceParagraph(normalizedParagraph)) return "source";
|
|
3551
|
+
const roles = getRagAnswerParagraphRoles(paragraphs);
|
|
3552
|
+
return paragraphs.map(normalizeRagParagraphText).some((candidate, index) => {
|
|
3553
|
+
return candidate === normalizedParagraph && roles[index] === "follow-up";
|
|
3554
|
+
}) ? "follow-up" : null;
|
|
3555
|
+
}
|
|
3556
|
+
function ragAnswerRoleClassName(role) {
|
|
3557
|
+
if (role === "source") return RAG_SOURCE_CLASS;
|
|
3558
|
+
if (role === "follow-up") return RAG_FOLLOW_UP_CLASS;
|
|
3559
|
+
return void 0;
|
|
3560
|
+
}
|
|
3561
|
+
function reactNodeText(node) {
|
|
3562
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
3563
|
+
if (Array.isArray(node)) return node.map(reactNodeText).join("");
|
|
3564
|
+
if (React.isValidElement(node)) {
|
|
3565
|
+
return reactNodeText(node.props.children);
|
|
3566
|
+
}
|
|
3567
|
+
return "";
|
|
3568
|
+
}
|
|
3569
|
+
function buildComponents(onImageClick, isResolvingRef, ragParagraphsRef) {
|
|
3440
3570
|
return {
|
|
3441
|
-
p: ({ children }) =>
|
|
3571
|
+
p: ({ children }) => {
|
|
3572
|
+
const role = getRagAnswerParagraphRole(
|
|
3573
|
+
reactNodeText(children),
|
|
3574
|
+
ragParagraphsRef?.current ?? []
|
|
3575
|
+
);
|
|
3576
|
+
return /* @__PURE__ */ jsx("p", { className: ragAnswerRoleClassName(role), children });
|
|
3577
|
+
},
|
|
3442
3578
|
code: ({ children }) => /* @__PURE__ */ jsx("code", { children }),
|
|
3443
3579
|
pre: ({ children }) => /* @__PURE__ */ jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsx("pre", { children }) }),
|
|
3444
3580
|
ul: ({ children }) => /* @__PURE__ */ jsx("ul", { children }),
|
|
@@ -3476,8 +3612,13 @@ function MarkdownRendererV2({
|
|
|
3476
3612
|
}) {
|
|
3477
3613
|
const isResolvingRef = useRef(isResolvingImages);
|
|
3478
3614
|
isResolvingRef.current = isResolvingImages;
|
|
3615
|
+
const ragParagraphsRef = useRef([]);
|
|
3616
|
+
ragParagraphsRef.current = useMemo(
|
|
3617
|
+
() => extractRagParagraphTexts(content),
|
|
3618
|
+
[content]
|
|
3619
|
+
);
|
|
3479
3620
|
const components = useMemo(
|
|
3480
|
-
() => buildComponents(onImageClick, isResolvingRef),
|
|
3621
|
+
() => buildComponents(onImageClick, isResolvingRef, ragParagraphsRef),
|
|
3481
3622
|
[onImageClick]
|
|
3482
3623
|
);
|
|
3483
3624
|
return /* @__PURE__ */ jsx(
|
|
@@ -3970,6 +4111,7 @@ function AssistantMessageV2({
|
|
|
3970
4111
|
return message.isStreaming ? stripIncompleteImageToken(normalized) : normalized;
|
|
3971
4112
|
})();
|
|
3972
4113
|
const isThinkingStreaming = !!message.isStreaming && !rawResponseContent && !message.isError;
|
|
4114
|
+
const showTrailingProgress = !!message.isStreaming && !!rawResponseContent && !message.isError && !message.isCancelled && !!message.hasTrailingActivity;
|
|
3973
4115
|
const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
|
|
3974
4116
|
const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(
|
|
3975
4117
|
rawResponseContent,
|
|
@@ -3978,6 +4120,8 @@ function AssistantMessageV2({
|
|
|
3978
4120
|
void 0,
|
|
3979
4121
|
typingSpeed
|
|
3980
4122
|
);
|
|
4123
|
+
const displayContentPending = Boolean(rawResponseContent) && !displayContent;
|
|
4124
|
+
const showThinkingBlock = isThinkingStreaming || displayContentPending;
|
|
3981
4125
|
const stickyLabel = (() => {
|
|
3982
4126
|
const steps = message.steps;
|
|
3983
4127
|
if (!steps || steps.length === 0) return void 0;
|
|
@@ -4112,7 +4256,7 @@ function AssistantMessageV2({
|
|
|
4112
4256
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4113
4257
|
toastPortal,
|
|
4114
4258
|
/* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: [
|
|
4115
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children:
|
|
4259
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: showThinkingBlock && /* @__PURE__ */ jsx(
|
|
4116
4260
|
motion.div,
|
|
4117
4261
|
{
|
|
4118
4262
|
initial: { opacity: 0, height: 0 },
|
|
@@ -4128,7 +4272,7 @@ function AssistantMessageV2({
|
|
|
4128
4272
|
{
|
|
4129
4273
|
isStreaming: isThinkingStreaming,
|
|
4130
4274
|
stickyLabel,
|
|
4131
|
-
currentStepLabel
|
|
4275
|
+
currentStepLabel: currentStepLabel ?? message.currentMessage
|
|
4132
4276
|
}
|
|
4133
4277
|
)
|
|
4134
4278
|
},
|
|
@@ -4142,7 +4286,32 @@ function AssistantMessageV2({
|
|
|
4142
4286
|
isResolvingImages: message.isResolvingImages,
|
|
4143
4287
|
onImageClick
|
|
4144
4288
|
}
|
|
4289
|
+
) : displayContentPending ? (
|
|
4290
|
+
// The intent/status line above is still bridging this
|
|
4291
|
+
// gap (see `showThinkingBlock`) — nothing to add here.
|
|
4292
|
+
null
|
|
4145
4293
|
) : !isThinkingStreaming ? /* @__PURE__ */ jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
|
|
4294
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: showTrailingProgress && /* @__PURE__ */ jsx(
|
|
4295
|
+
motion.div,
|
|
4296
|
+
{
|
|
4297
|
+
initial: { opacity: 0, height: 0 },
|
|
4298
|
+
animate: { opacity: 1, height: "auto" },
|
|
4299
|
+
exit: { opacity: 0, height: 0 },
|
|
4300
|
+
transition: {
|
|
4301
|
+
duration: 0.32,
|
|
4302
|
+
ease: [0.2, 0, 0, 1]
|
|
4303
|
+
},
|
|
4304
|
+
style: { overflow: "hidden" },
|
|
4305
|
+
children: /* @__PURE__ */ jsx(
|
|
4306
|
+
ThinkingBlockV2,
|
|
4307
|
+
{
|
|
4308
|
+
isStreaming: true,
|
|
4309
|
+
currentStepLabel: message.currentMessage ?? currentStepLabel
|
|
4310
|
+
}
|
|
4311
|
+
)
|
|
4312
|
+
},
|
|
4313
|
+
"trailing-progress"
|
|
4314
|
+
) }),
|
|
4146
4315
|
isCancelled && message.isStreaming && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-paused", children: [
|
|
4147
4316
|
/* @__PURE__ */ jsx(
|
|
4148
4317
|
WifiOff,
|
|
@@ -4241,6 +4410,112 @@ function AssistantMessageV2({
|
|
|
4241
4410
|
)
|
|
4242
4411
|
] });
|
|
4243
4412
|
}
|
|
4413
|
+
var CHAR_VARIANTS = {
|
|
4414
|
+
fade: {
|
|
4415
|
+
initial: { opacity: 0, scale: 0.7 },
|
|
4416
|
+
animate: { opacity: 1, scale: 1 },
|
|
4417
|
+
exit: { opacity: 0, scale: 0.7 },
|
|
4418
|
+
transition: { duration: 0.14, ease: "easeOut" },
|
|
4419
|
+
overflow: "hidden"
|
|
4420
|
+
},
|
|
4421
|
+
blur: {
|
|
4422
|
+
initial: { opacity: 0, filter: "blur(8px)", y: -8 },
|
|
4423
|
+
animate: { opacity: 1, filter: "blur(0px)", y: 0 },
|
|
4424
|
+
exit: { opacity: 0, filter: "blur(8px)", y: 8 },
|
|
4425
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
4426
|
+
overflow: "visible"
|
|
4427
|
+
}
|
|
4428
|
+
};
|
|
4429
|
+
function CharSlot({
|
|
4430
|
+
char,
|
|
4431
|
+
charKey,
|
|
4432
|
+
effect
|
|
4433
|
+
}) {
|
|
4434
|
+
if (!/\d/.test(char)) return /* @__PURE__ */ jsx("span", { style: { display: "inline-block" }, children: char });
|
|
4435
|
+
const v = CHAR_VARIANTS[effect];
|
|
4436
|
+
return /* @__PURE__ */ jsx("span", { style: { position: "relative", display: "inline-block", overflow: v.overflow }, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsx(
|
|
4437
|
+
motion.span,
|
|
4438
|
+
{
|
|
4439
|
+
initial: v.initial,
|
|
4440
|
+
animate: v.animate,
|
|
4441
|
+
exit: v.exit,
|
|
4442
|
+
transition: v.transition,
|
|
4443
|
+
style: { display: "inline-block" },
|
|
4444
|
+
children: char
|
|
4445
|
+
},
|
|
4446
|
+
charKey
|
|
4447
|
+
) }) });
|
|
4448
|
+
}
|
|
4449
|
+
function CountUp({
|
|
4450
|
+
to,
|
|
4451
|
+
from = 0,
|
|
4452
|
+
duration = 2,
|
|
4453
|
+
delay = 0,
|
|
4454
|
+
digitEffect = "none",
|
|
4455
|
+
className,
|
|
4456
|
+
startWhen = true,
|
|
4457
|
+
separator = ""
|
|
4458
|
+
}) {
|
|
4459
|
+
const ref = useRef(null);
|
|
4460
|
+
const motionValue = useMotionValue(from);
|
|
4461
|
+
const damping = 20 + 40 * (1 / duration);
|
|
4462
|
+
const stiffness = 100 * (1 / duration);
|
|
4463
|
+
const springValue = useSpring(motionValue, { damping, stiffness });
|
|
4464
|
+
const isInView = useInView(ref, { once: true, margin: "0px" });
|
|
4465
|
+
const decimals = useMemo(() => {
|
|
4466
|
+
const d = (n) => {
|
|
4467
|
+
const s = n.toString();
|
|
4468
|
+
return s.includes(".") ? s.split(".")[1].length : 0;
|
|
4469
|
+
};
|
|
4470
|
+
return Math.max(d(from), d(to));
|
|
4471
|
+
}, [from, to]);
|
|
4472
|
+
const formatValue = useCallback(
|
|
4473
|
+
(latest) => {
|
|
4474
|
+
const formatted = Intl.NumberFormat("en-US", {
|
|
4475
|
+
useGrouping: !!separator,
|
|
4476
|
+
minimumFractionDigits: decimals,
|
|
4477
|
+
maximumFractionDigits: decimals
|
|
4478
|
+
}).format(latest);
|
|
4479
|
+
return separator ? formatted.replace(/,/g, separator) : formatted;
|
|
4480
|
+
},
|
|
4481
|
+
[decimals, separator]
|
|
4482
|
+
);
|
|
4483
|
+
const [chars, setChars] = useState(formatValue(from).split(""));
|
|
4484
|
+
useEffect(() => {
|
|
4485
|
+
if (isInView && startWhen) {
|
|
4486
|
+
const t = setTimeout(() => motionValue.set(to), delay * 1e3);
|
|
4487
|
+
return () => clearTimeout(t);
|
|
4488
|
+
}
|
|
4489
|
+
}, [isInView, startWhen, motionValue, to, delay]);
|
|
4490
|
+
useEffect(() => {
|
|
4491
|
+
const unsub = springValue.on("change", (latest) => {
|
|
4492
|
+
if (digitEffect === "none") {
|
|
4493
|
+
if (ref.current) ref.current.textContent = formatValue(latest);
|
|
4494
|
+
} else {
|
|
4495
|
+
setChars(formatValue(latest).split(""));
|
|
4496
|
+
}
|
|
4497
|
+
});
|
|
4498
|
+
return () => unsub();
|
|
4499
|
+
}, [springValue, formatValue, digitEffect]);
|
|
4500
|
+
if (digitEffect === "none") {
|
|
4501
|
+
return /* @__PURE__ */ jsx("span", { ref, className: cn(className), children: formatValue(from) });
|
|
4502
|
+
}
|
|
4503
|
+
return /* @__PURE__ */ jsx("span", { ref, className: cn("inline-flex items-center", className), children: chars.map((char, i) => /* @__PURE__ */ jsx(CharSlot, { char, charKey: `${i}-${char}`, effect: digitEffect }, i)) });
|
|
4504
|
+
}
|
|
4505
|
+
function AnimatedDuration({ seconds, className }) {
|
|
4506
|
+
const total = Math.max(0, seconds);
|
|
4507
|
+
const m = Math.floor(total / 60);
|
|
4508
|
+
const s = total % 60;
|
|
4509
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("tabular-nums", className), children: [
|
|
4510
|
+
m > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4511
|
+
/* @__PURE__ */ jsx(CountUp, { to: m, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4512
|
+
"m",
|
|
4513
|
+
" "
|
|
4514
|
+
] }),
|
|
4515
|
+
/* @__PURE__ */ jsx(CountUp, { to: s, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4516
|
+
"s"
|
|
4517
|
+
] });
|
|
4518
|
+
}
|
|
4244
4519
|
var DEFAULT_MAX_LENGTH = 6;
|
|
4245
4520
|
var MAX_SUPPORTED_LENGTH = 12;
|
|
4246
4521
|
var AUTO_FOCUS_DELAY_MS = 250;
|
|
@@ -4367,7 +4642,6 @@ function VerificationInline({
|
|
|
4367
4642
|
useEffect(() => {
|
|
4368
4643
|
if (prompt.subAction === "SubmissionInvalid") {
|
|
4369
4644
|
setErrored(true);
|
|
4370
|
-
setCode("");
|
|
4371
4645
|
lastSubmittedRef.current = null;
|
|
4372
4646
|
}
|
|
4373
4647
|
}, [prompt.subAction, prompt.userActionId]);
|
|
@@ -4437,15 +4711,18 @@ function VerificationInline({
|
|
|
4437
4711
|
if (busy) return;
|
|
4438
4712
|
void onCancel(prompt.userActionId);
|
|
4439
4713
|
}, [busy, onCancel, prompt.userActionId]);
|
|
4440
|
-
const
|
|
4714
|
+
const promptMessage = prompt.message?.trim();
|
|
4715
|
+
const description = promptMessage || (isNumeric ? `Enter the ${codeLen}-digit code to continue` : "Enter the verification code to continue");
|
|
4716
|
+
const messageFormat = prompt.metadata?.["payman/messageFormat"];
|
|
4717
|
+
const renderMarkdown = !!promptMessage && messageFormat === "markdown";
|
|
4441
4718
|
if (hiddenAfterResend) return null;
|
|
4442
4719
|
return /* @__PURE__ */ jsxs("div", { className: "payman-v2-ua", role: "group", "aria-label": "Verification required", children: [
|
|
4443
4720
|
/* @__PURE__ */ jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4444
4721
|
/* @__PURE__ */ jsx(ShieldCheck, { className: "payman-v2-ua-icon", size: 15, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4445
4722
|
/* @__PURE__ */ jsx("span", { className: "payman-v2-ua-title", children: "Verification required" }),
|
|
4446
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
4723
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4447
4724
|
] }),
|
|
4448
|
-
/* @__PURE__ */ jsx("p", { className: "payman-v2-ua-desc", children: description }),
|
|
4725
|
+
renderMarkdown ? /* @__PURE__ */ jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsx(MarkdownRendererV2, { content: description }) }) : /* @__PURE__ */ jsx("p", { className: "payman-v2-ua-desc", children: description }),
|
|
4449
4726
|
stale ? /* @__PURE__ */ jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4450
4727
|
isNumeric ? /* @__PURE__ */ jsx("div", { className: "payman-v2-ua-field", children: /* @__PURE__ */ jsx(
|
|
4451
4728
|
OtpInputV2,
|
|
@@ -4515,6 +4792,228 @@ function VerificationInline({
|
|
|
4515
4792
|
] })
|
|
4516
4793
|
] });
|
|
4517
4794
|
}
|
|
4795
|
+
function AmountFieldV2({
|
|
4796
|
+
id,
|
|
4797
|
+
value,
|
|
4798
|
+
onChange,
|
|
4799
|
+
disabled,
|
|
4800
|
+
className,
|
|
4801
|
+
onEnter
|
|
4802
|
+
}) {
|
|
4803
|
+
const inputRef = useRef(null);
|
|
4804
|
+
const digits = digitsFromValue(value);
|
|
4805
|
+
const display = formatDigits(digits);
|
|
4806
|
+
useLayoutEffect(() => {
|
|
4807
|
+
const el = inputRef.current;
|
|
4808
|
+
if (el && document.activeElement === el) {
|
|
4809
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
4810
|
+
}
|
|
4811
|
+
}, [display]);
|
|
4812
|
+
return /* @__PURE__ */ jsx(
|
|
4813
|
+
"input",
|
|
4814
|
+
{
|
|
4815
|
+
ref: inputRef,
|
|
4816
|
+
id,
|
|
4817
|
+
type: "text",
|
|
4818
|
+
inputMode: "decimal",
|
|
4819
|
+
autoComplete: "off",
|
|
4820
|
+
className,
|
|
4821
|
+
value: display,
|
|
4822
|
+
placeholder: "0.00",
|
|
4823
|
+
disabled,
|
|
4824
|
+
onChange: (e) => {
|
|
4825
|
+
onChange(valueFromDigits(digitsFromDisplay(e.target.value)));
|
|
4826
|
+
},
|
|
4827
|
+
onKeyDown: (e) => {
|
|
4828
|
+
if (e.key === "Enter") {
|
|
4829
|
+
e.preventDefault();
|
|
4830
|
+
onEnter?.();
|
|
4831
|
+
}
|
|
4832
|
+
},
|
|
4833
|
+
onFocus: (e) => {
|
|
4834
|
+
const el = e.currentTarget;
|
|
4835
|
+
requestAnimationFrame(() => el.setSelectionRange(el.value.length, el.value.length));
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
);
|
|
4839
|
+
}
|
|
4840
|
+
function digitsFromDisplay(raw) {
|
|
4841
|
+
return raw.replace(/[^0-9]/g, "").replace(/^0+(?=\d)/, "").slice(-9);
|
|
4842
|
+
}
|
|
4843
|
+
function digitsFromValue(value) {
|
|
4844
|
+
const num = Number(value);
|
|
4845
|
+
if (!value || !Number.isFinite(num) || num <= 0) return "";
|
|
4846
|
+
return String(Math.round(num * 100));
|
|
4847
|
+
}
|
|
4848
|
+
function formatDigits(digits) {
|
|
4849
|
+
if (!digits) return "";
|
|
4850
|
+
const padded = digits.padStart(3, "0");
|
|
4851
|
+
const cents = padded.slice(-2);
|
|
4852
|
+
const whole = padded.slice(0, -2).replace(/^0+(?=\d)/, "") || "0";
|
|
4853
|
+
const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
4854
|
+
return `${grouped}.${cents}`;
|
|
4855
|
+
}
|
|
4856
|
+
function valueFromDigits(digits) {
|
|
4857
|
+
if (!digits) return "";
|
|
4858
|
+
return (Number(digits) / 100).toString();
|
|
4859
|
+
}
|
|
4860
|
+
function findRootClassName(el) {
|
|
4861
|
+
const root = el?.closest(".payman-v2-root");
|
|
4862
|
+
return root instanceof HTMLElement ? root.className : "";
|
|
4863
|
+
}
|
|
4864
|
+
var MENU_MAX_HEIGHT = 240;
|
|
4865
|
+
var OPTION_HEIGHT = 34;
|
|
4866
|
+
var VIEWPORT_MARGIN = 8;
|
|
4867
|
+
function SelectFieldV2({
|
|
4868
|
+
id,
|
|
4869
|
+
value,
|
|
4870
|
+
options,
|
|
4871
|
+
onChange,
|
|
4872
|
+
disabled,
|
|
4873
|
+
error,
|
|
4874
|
+
placeholder = "Select\u2026"
|
|
4875
|
+
}) {
|
|
4876
|
+
const triggerRef = useRef(null);
|
|
4877
|
+
const listRef = useRef(null);
|
|
4878
|
+
const [open, setOpen] = useState(false);
|
|
4879
|
+
const [rect, setRect] = useState(null);
|
|
4880
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
4881
|
+
const [rootClassName, setRootClassName] = useState("");
|
|
4882
|
+
const selected = options.find((o) => o.const === value);
|
|
4883
|
+
useLayoutEffect(() => {
|
|
4884
|
+
if (!open) return;
|
|
4885
|
+
const place = () => {
|
|
4886
|
+
const el = triggerRef.current;
|
|
4887
|
+
if (!el) return;
|
|
4888
|
+
const r = el.getBoundingClientRect();
|
|
4889
|
+
const viewportH = window.innerHeight;
|
|
4890
|
+
const estimatedMenuH = Math.min(
|
|
4891
|
+
options.length * OPTION_HEIGHT + VIEWPORT_MARGIN,
|
|
4892
|
+
MENU_MAX_HEIGHT
|
|
4893
|
+
);
|
|
4894
|
+
const spaceBelow = viewportH - r.bottom;
|
|
4895
|
+
const spaceAbove = r.top;
|
|
4896
|
+
const openUp = spaceBelow < estimatedMenuH && spaceAbove > spaceBelow;
|
|
4897
|
+
setRect({ top: r.bottom, bottom: viewportH - r.top, left: r.left, width: r.width, openUp });
|
|
4898
|
+
setRootClassName(findRootClassName(el));
|
|
4899
|
+
};
|
|
4900
|
+
place();
|
|
4901
|
+
window.addEventListener("resize", place);
|
|
4902
|
+
window.addEventListener("scroll", place, true);
|
|
4903
|
+
return () => {
|
|
4904
|
+
window.removeEventListener("resize", place);
|
|
4905
|
+
window.removeEventListener("scroll", place, true);
|
|
4906
|
+
};
|
|
4907
|
+
}, [open, options.length]);
|
|
4908
|
+
useEffect(() => {
|
|
4909
|
+
if (!open) return;
|
|
4910
|
+
setActiveIndex(Math.max(0, options.findIndex((o) => o.const === value)));
|
|
4911
|
+
listRef.current?.focus();
|
|
4912
|
+
}, [open]);
|
|
4913
|
+
useEffect(() => {
|
|
4914
|
+
if (!open) return;
|
|
4915
|
+
const onDocDown = (e) => {
|
|
4916
|
+
const target = e.target;
|
|
4917
|
+
if (triggerRef.current?.contains(target) || listRef.current?.contains(target)) return;
|
|
4918
|
+
setOpen(false);
|
|
4919
|
+
};
|
|
4920
|
+
document.addEventListener("mousedown", onDocDown);
|
|
4921
|
+
return () => document.removeEventListener("mousedown", onDocDown);
|
|
4922
|
+
}, [open]);
|
|
4923
|
+
const commit = (opt) => {
|
|
4924
|
+
onChange(opt.const);
|
|
4925
|
+
setOpen(false);
|
|
4926
|
+
triggerRef.current?.focus();
|
|
4927
|
+
};
|
|
4928
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4929
|
+
/* @__PURE__ */ jsxs(
|
|
4930
|
+
"button",
|
|
4931
|
+
{
|
|
4932
|
+
ref: triggerRef,
|
|
4933
|
+
id,
|
|
4934
|
+
type: "button",
|
|
4935
|
+
disabled,
|
|
4936
|
+
className: cn("payman-v2-ua-select-trigger", error && "payman-v2-ua-input-error"),
|
|
4937
|
+
"aria-haspopup": "listbox",
|
|
4938
|
+
"aria-expanded": open,
|
|
4939
|
+
onClick: () => setOpen((v) => !v),
|
|
4940
|
+
onKeyDown: (e) => {
|
|
4941
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
4942
|
+
e.preventDefault();
|
|
4943
|
+
setOpen(true);
|
|
4944
|
+
}
|
|
4945
|
+
},
|
|
4946
|
+
children: [
|
|
4947
|
+
/* @__PURE__ */ jsx(
|
|
4948
|
+
"span",
|
|
4949
|
+
{
|
|
4950
|
+
className: cn(
|
|
4951
|
+
"payman-v2-ua-select-value",
|
|
4952
|
+
!selected && "payman-v2-ua-select-placeholder"
|
|
4953
|
+
),
|
|
4954
|
+
children: selected ? selected.title || selected.const : placeholder
|
|
4955
|
+
}
|
|
4956
|
+
),
|
|
4957
|
+
/* @__PURE__ */ jsx(ChevronDown, { size: 14, className: "payman-v2-ua-select-chevron", "aria-hidden": true })
|
|
4958
|
+
]
|
|
4959
|
+
}
|
|
4960
|
+
),
|
|
4961
|
+
open && rect && typeof document !== "undefined" && createPortal(
|
|
4962
|
+
/* @__PURE__ */ jsx(
|
|
4963
|
+
"div",
|
|
4964
|
+
{
|
|
4965
|
+
ref: listRef,
|
|
4966
|
+
role: "listbox",
|
|
4967
|
+
className: cn(rootClassName, "payman-v2-ua-select-menu"),
|
|
4968
|
+
tabIndex: -1,
|
|
4969
|
+
style: {
|
|
4970
|
+
position: "fixed",
|
|
4971
|
+
left: rect.left,
|
|
4972
|
+
width: rect.width,
|
|
4973
|
+
height: "fit-content",
|
|
4974
|
+
maxHeight: MENU_MAX_HEIGHT,
|
|
4975
|
+
...rect.openUp ? { bottom: rect.bottom } : { top: rect.top }
|
|
4976
|
+
},
|
|
4977
|
+
onKeyDown: (e) => {
|
|
4978
|
+
if (e.key === "ArrowDown") {
|
|
4979
|
+
e.preventDefault();
|
|
4980
|
+
setActiveIndex((i) => Math.min(options.length - 1, i + 1));
|
|
4981
|
+
} else if (e.key === "ArrowUp") {
|
|
4982
|
+
e.preventDefault();
|
|
4983
|
+
setActiveIndex((i) => Math.max(0, i - 1));
|
|
4984
|
+
} else if (e.key === "Enter" || e.key === " ") {
|
|
4985
|
+
e.preventDefault();
|
|
4986
|
+
if (activeIndex >= 0) commit(options[activeIndex]);
|
|
4987
|
+
} else if (e.key === "Escape" || e.key === "Tab") {
|
|
4988
|
+
setOpen(false);
|
|
4989
|
+
triggerRef.current?.focus();
|
|
4990
|
+
}
|
|
4991
|
+
},
|
|
4992
|
+
children: options.map((opt, i) => /* @__PURE__ */ jsxs(
|
|
4993
|
+
"div",
|
|
4994
|
+
{
|
|
4995
|
+
role: "option",
|
|
4996
|
+
"aria-selected": opt.const === value,
|
|
4997
|
+
className: cn(
|
|
4998
|
+
"payman-v2-ua-select-option",
|
|
4999
|
+
i === activeIndex && "payman-v2-ua-select-option-active",
|
|
5000
|
+
opt.const === value && "payman-v2-ua-select-option-selected"
|
|
5001
|
+
),
|
|
5002
|
+
onMouseEnter: () => setActiveIndex(i),
|
|
5003
|
+
onClick: () => commit(opt),
|
|
5004
|
+
children: [
|
|
5005
|
+
/* @__PURE__ */ jsx("span", { children: opt.title || opt.const }),
|
|
5006
|
+
opt.const === value && /* @__PURE__ */ jsx(Check, { size: 13, "aria-hidden": true })
|
|
5007
|
+
]
|
|
5008
|
+
},
|
|
5009
|
+
opt.const
|
|
5010
|
+
))
|
|
5011
|
+
}
|
|
5012
|
+
),
|
|
5013
|
+
document.body
|
|
5014
|
+
)
|
|
5015
|
+
] });
|
|
5016
|
+
}
|
|
4518
5017
|
function SchemaFormInline({
|
|
4519
5018
|
prompt,
|
|
4520
5019
|
secondsLeft,
|
|
@@ -4560,7 +5059,7 @@ function SchemaFormInline({
|
|
|
4560
5059
|
/* @__PURE__ */ jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4561
5060
|
/* @__PURE__ */ jsx(Pencil, { className: "payman-v2-ua-icon", size: 14, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4562
5061
|
/* @__PURE__ */ jsx("span", { className: "payman-v2-ua-title", children: "Action required" }),
|
|
4563
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
5062
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4564
5063
|
] }),
|
|
4565
5064
|
prompt.message?.trim() && (renderMarkdown ? /* @__PURE__ */ jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsx(MarkdownRendererV2, { content: prompt.message }) }) : /* @__PURE__ */ jsx("p", { className: "payman-v2-ua-desc", children: prompt.message })),
|
|
4566
5065
|
stale ? /* @__PURE__ */ jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : fields.length === 0 ? null : /* @__PURE__ */ jsx("div", { className: "payman-v2-ua-form", children: fields.map(([key, field]) => {
|
|
@@ -4592,26 +5091,33 @@ function SchemaFormInline({
|
|
|
4592
5091
|
required && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-req", children: "*" })
|
|
4593
5092
|
] }),
|
|
4594
5093
|
field.description && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-hint", children: field.description }),
|
|
4595
|
-
widget === "select" ? /* @__PURE__ */
|
|
4596
|
-
|
|
5094
|
+
widget === "select" ? /* @__PURE__ */ jsx(
|
|
5095
|
+
SelectFieldV2,
|
|
4597
5096
|
{
|
|
4598
5097
|
id: fieldId,
|
|
4599
|
-
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4600
5098
|
value: String(values[key] ?? ""),
|
|
5099
|
+
options: getOptions(field),
|
|
4601
5100
|
disabled: locked,
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
5101
|
+
error: Boolean(err),
|
|
5102
|
+
onChange: (v) => setValue(key, v)
|
|
5103
|
+
}
|
|
5104
|
+
) : widget === "decimal" ? /* @__PURE__ */ jsx(
|
|
5105
|
+
AmountFieldV2,
|
|
5106
|
+
{
|
|
5107
|
+
id: fieldId,
|
|
5108
|
+
value: String(values[key] ?? ""),
|
|
5109
|
+
disabled: locked,
|
|
5110
|
+
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
5111
|
+
onChange: (v) => setValue(key, v),
|
|
5112
|
+
onEnter: handleSubmit
|
|
4607
5113
|
}
|
|
4608
5114
|
) : /* @__PURE__ */ jsx(
|
|
4609
5115
|
"input",
|
|
4610
5116
|
{
|
|
4611
5117
|
id: fieldId,
|
|
4612
|
-
type: widget === "integer"
|
|
4613
|
-
inputMode: widget === "integer" ? "numeric" :
|
|
4614
|
-
step: widget === "
|
|
5118
|
+
type: widget === "integer" ? "number" : "text",
|
|
5119
|
+
inputMode: widget === "integer" ? "numeric" : void 0,
|
|
5120
|
+
step: widget === "integer" ? "1" : void 0,
|
|
4615
5121
|
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4616
5122
|
value: String(values[key] ?? ""),
|
|
4617
5123
|
disabled: locked,
|
|
@@ -4708,12 +5214,16 @@ function UserActionInline({
|
|
|
4708
5214
|
onSubmit,
|
|
4709
5215
|
onCancel,
|
|
4710
5216
|
onResend,
|
|
4711
|
-
onExpired
|
|
5217
|
+
onExpired,
|
|
5218
|
+
suppressExpiredNote
|
|
4712
5219
|
}) {
|
|
4713
5220
|
const [secondsLeft, expired] = useExpiryCountdown(prompt);
|
|
4714
5221
|
useEffect(() => {
|
|
4715
5222
|
if (expired && prompt.kind !== "notification") onExpired?.();
|
|
4716
5223
|
}, [expired, onExpired, prompt.kind]);
|
|
5224
|
+
if (expired && prompt.kind !== "notification" && suppressExpiredNote) {
|
|
5225
|
+
return null;
|
|
5226
|
+
}
|
|
4717
5227
|
let body;
|
|
4718
5228
|
if (expired && prompt.kind !== "notification") {
|
|
4719
5229
|
const note = {
|
|
@@ -4774,6 +5284,9 @@ function getPromptViewKey(prompt) {
|
|
|
4774
5284
|
prompt.message ?? ""
|
|
4775
5285
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4776
5286
|
}
|
|
5287
|
+
function getPromptMountKey(prompt) {
|
|
5288
|
+
return [getPromptSlotKey(prompt), prompt.userActionId].join(PROMPT_KEY_SEPARATOR);
|
|
5289
|
+
}
|
|
4777
5290
|
var MessageListV2 = forwardRef(
|
|
4778
5291
|
function MessageListV22({
|
|
4779
5292
|
messages,
|
|
@@ -4785,6 +5298,7 @@ var MessageListV2 = forwardRef(
|
|
|
4785
5298
|
messageActions,
|
|
4786
5299
|
retryDisabled = false,
|
|
4787
5300
|
userActionPrompts,
|
|
5301
|
+
dockedUserActionId,
|
|
4788
5302
|
notifications,
|
|
4789
5303
|
onSubmitUserAction,
|
|
4790
5304
|
onCancelUserAction,
|
|
@@ -4893,10 +5407,11 @@ var MessageListV2 = forwardRef(
|
|
|
4893
5407
|
}, [userActionPrompts]);
|
|
4894
5408
|
const visibleUserActionPrompts = useMemo(
|
|
4895
5409
|
() => userActionPrompts?.filter((prompt) => {
|
|
5410
|
+
if (prompt.userActionId === dockedUserActionId) return false;
|
|
4896
5411
|
const promptKey = getPromptViewKey(prompt);
|
|
4897
5412
|
return !expiredPromptViewState[promptKey]?.hidden;
|
|
4898
5413
|
}),
|
|
4899
|
-
[expiredPromptViewState, userActionPrompts]
|
|
5414
|
+
[dockedUserActionId, expiredPromptViewState, userActionPrompts]
|
|
4900
5415
|
);
|
|
4901
5416
|
const pinToBottom = useCallback((behavior = "instant") => {
|
|
4902
5417
|
const el = scrollRef.current;
|
|
@@ -5045,7 +5560,7 @@ var MessageListV2 = forwardRef(
|
|
|
5045
5560
|
onResend: onResendUserAction ?? noop,
|
|
5046
5561
|
onExpired: () => handleUserActionExpired(promptKey, prompt.userActionId)
|
|
5047
5562
|
},
|
|
5048
|
-
|
|
5563
|
+
getPromptMountKey(prompt)
|
|
5049
5564
|
);
|
|
5050
5565
|
})
|
|
5051
5566
|
]
|
|
@@ -5591,10 +6106,455 @@ var ChatInputV2 = forwardRef(
|
|
|
5591
6106
|
] });
|
|
5592
6107
|
}
|
|
5593
6108
|
);
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
6109
|
+
function dockKey(prompt) {
|
|
6110
|
+
return `${prompt.toolCallId || prompt.userActionId}:${prompt.userActionId}`;
|
|
6111
|
+
}
|
|
6112
|
+
function UserActionDock({
|
|
6113
|
+
prompt,
|
|
6114
|
+
onSubmit,
|
|
6115
|
+
onCancel,
|
|
6116
|
+
onResend,
|
|
6117
|
+
onExpired,
|
|
6118
|
+
children
|
|
6119
|
+
}) {
|
|
6120
|
+
return /* @__PURE__ */ jsx("div", { className: "payman-v2-ua-dock", children: /* @__PURE__ */ jsx(motion.div, { layout: "size", transition: { duration: 0.3, ease: [0.2, 0, 0, 1] }, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", initial: false, children: prompt ? /* @__PURE__ */ jsx(
|
|
6121
|
+
motion.div,
|
|
6122
|
+
{
|
|
6123
|
+
initial: { opacity: 0 },
|
|
6124
|
+
animate: { opacity: 1 },
|
|
6125
|
+
exit: { opacity: 0 },
|
|
6126
|
+
transition: { duration: 0.15 },
|
|
6127
|
+
className: "payman-v2-ua-dock-panel",
|
|
6128
|
+
children: /* @__PURE__ */ jsx(
|
|
6129
|
+
UserActionInline,
|
|
6130
|
+
{
|
|
6131
|
+
prompt,
|
|
6132
|
+
onSubmit,
|
|
6133
|
+
onCancel,
|
|
6134
|
+
onResend,
|
|
6135
|
+
onExpired: () => onExpired?.(prompt.userActionId),
|
|
6136
|
+
suppressExpiredNote: true
|
|
6137
|
+
}
|
|
6138
|
+
)
|
|
6139
|
+
},
|
|
6140
|
+
dockKey(prompt)
|
|
6141
|
+
) : /* @__PURE__ */ jsx(
|
|
6142
|
+
motion.div,
|
|
6143
|
+
{
|
|
6144
|
+
initial: { opacity: 0 },
|
|
6145
|
+
animate: { opacity: 1 },
|
|
6146
|
+
exit: { opacity: 0 },
|
|
6147
|
+
transition: { duration: 0.15 },
|
|
6148
|
+
children
|
|
6149
|
+
},
|
|
6150
|
+
"composer"
|
|
6151
|
+
) }) }) });
|
|
6152
|
+
}
|
|
6153
|
+
function clamp(value) {
|
|
6154
|
+
return Math.max(0, Math.min(1, value));
|
|
6155
|
+
}
|
|
6156
|
+
function ensureFrameSize(frame, rows, cols) {
|
|
6157
|
+
const result = [];
|
|
6158
|
+
for (let r = 0; r < rows; r++) {
|
|
6159
|
+
const row = frame[r] || [];
|
|
6160
|
+
result.push([]);
|
|
6161
|
+
for (let c = 0; c < cols; c++) {
|
|
6162
|
+
result[r][c] = row[c] ?? 0;
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
return result;
|
|
6166
|
+
}
|
|
6167
|
+
function useAnimation(frames, options) {
|
|
6168
|
+
const [frameIndex, setFrameIndex] = useState(0);
|
|
6169
|
+
const [isPlaying, setIsPlaying] = useState(options.autoplay);
|
|
6170
|
+
const frameIdRef = useRef(void 0);
|
|
6171
|
+
const lastTimeRef = useRef(0);
|
|
6172
|
+
const accumulatorRef = useRef(0);
|
|
6173
|
+
useEffect(() => {
|
|
6174
|
+
if (!frames || frames.length === 0 || !isPlaying) {
|
|
6175
|
+
return;
|
|
6176
|
+
}
|
|
6177
|
+
const frameInterval = 1e3 / options.fps;
|
|
6178
|
+
const animate = (currentTime) => {
|
|
6179
|
+
if (lastTimeRef.current === 0) {
|
|
6180
|
+
lastTimeRef.current = currentTime;
|
|
6181
|
+
}
|
|
6182
|
+
const deltaTime = currentTime - lastTimeRef.current;
|
|
6183
|
+
lastTimeRef.current = currentTime;
|
|
6184
|
+
accumulatorRef.current += deltaTime;
|
|
6185
|
+
if (accumulatorRef.current >= frameInterval) {
|
|
6186
|
+
accumulatorRef.current -= frameInterval;
|
|
6187
|
+
setFrameIndex((prev) => {
|
|
6188
|
+
const next = prev + 1;
|
|
6189
|
+
if (next >= frames.length) {
|
|
6190
|
+
if (options.loop) {
|
|
6191
|
+
options.onFrame?.(0);
|
|
6192
|
+
return 0;
|
|
6193
|
+
} else {
|
|
6194
|
+
setIsPlaying(false);
|
|
6195
|
+
return prev;
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
options.onFrame?.(next);
|
|
6199
|
+
return next;
|
|
6200
|
+
});
|
|
6201
|
+
}
|
|
6202
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6203
|
+
};
|
|
6204
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6205
|
+
return () => {
|
|
6206
|
+
if (frameIdRef.current) {
|
|
6207
|
+
cancelAnimationFrame(frameIdRef.current);
|
|
6208
|
+
}
|
|
6209
|
+
};
|
|
6210
|
+
}, [frames, isPlaying, options.fps, options.loop, options.onFrame]);
|
|
6211
|
+
useEffect(() => {
|
|
6212
|
+
setFrameIndex(0);
|
|
6213
|
+
setIsPlaying(options.autoplay);
|
|
6214
|
+
lastTimeRef.current = 0;
|
|
6215
|
+
accumulatorRef.current = 0;
|
|
6216
|
+
}, [frames, options.autoplay]);
|
|
6217
|
+
return { frameIndex, isPlaying };
|
|
6218
|
+
}
|
|
6219
|
+
function emptyFrame(rows, cols) {
|
|
6220
|
+
return Array.from({ length: rows }, () => Array(cols).fill(0));
|
|
6221
|
+
}
|
|
6222
|
+
function setPixel(frame, row, col, value) {
|
|
6223
|
+
if (row >= 0 && row < frame.length && col >= 0 && col < frame[0].length) {
|
|
6224
|
+
frame[row][col] = value;
|
|
6225
|
+
}
|
|
6226
|
+
}
|
|
6227
|
+
var loader = (() => {
|
|
6228
|
+
const frames = [];
|
|
6229
|
+
const size = 7;
|
|
6230
|
+
const center = 3;
|
|
6231
|
+
const radius = 2.5;
|
|
6232
|
+
for (let frame = 0; frame < 12; frame++) {
|
|
6233
|
+
const f = emptyFrame(size, size);
|
|
6234
|
+
for (let i = 0; i < 8; i++) {
|
|
6235
|
+
const angle = frame / 12 * Math.PI * 2 + i / 8 * Math.PI * 2;
|
|
6236
|
+
const x = Math.round(center + Math.cos(angle) * radius);
|
|
6237
|
+
const y = Math.round(center + Math.sin(angle) * radius);
|
|
6238
|
+
const brightness = 1 - i / 10;
|
|
6239
|
+
setPixel(f, y, x, Math.max(0.2, brightness));
|
|
6240
|
+
}
|
|
6241
|
+
frames.push(f);
|
|
6242
|
+
}
|
|
6243
|
+
return frames;
|
|
6244
|
+
})();
|
|
6245
|
+
var pulse = (() => {
|
|
6246
|
+
const frames = [];
|
|
6247
|
+
const size = 7;
|
|
6248
|
+
const center = 3;
|
|
6249
|
+
for (let frame = 0; frame < 16; frame++) {
|
|
6250
|
+
const f = emptyFrame(size, size);
|
|
6251
|
+
const phase = frame / 16 * Math.PI * 2;
|
|
6252
|
+
const intensity = (Math.sin(phase) + 1) / 2;
|
|
6253
|
+
setPixel(f, center, center, 1);
|
|
6254
|
+
const radius = Math.floor((1 - intensity) * 3) + 1;
|
|
6255
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
6256
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
6257
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
6258
|
+
if (Math.abs(dist - radius) < 0.7) {
|
|
6259
|
+
setPixel(f, center + dy, center + dx, intensity * 0.6);
|
|
6260
|
+
}
|
|
6261
|
+
}
|
|
6262
|
+
}
|
|
6263
|
+
frames.push(f);
|
|
6264
|
+
}
|
|
6265
|
+
return frames;
|
|
6266
|
+
})();
|
|
6267
|
+
function vu(columns, levels) {
|
|
6268
|
+
const rows = 7;
|
|
6269
|
+
const frame = emptyFrame(rows, columns);
|
|
6270
|
+
for (let col = 0; col < Math.min(columns, levels.length); col++) {
|
|
6271
|
+
const level = Math.max(0, Math.min(1, levels[col]));
|
|
6272
|
+
const height = Math.floor(level * rows);
|
|
6273
|
+
for (let row = 0; row < rows; row++) {
|
|
6274
|
+
const rowFromBottom = rows - 1 - row;
|
|
6275
|
+
if (rowFromBottom < height) {
|
|
6276
|
+
let brightness = 1;
|
|
6277
|
+
if (row < rows * 0.3) {
|
|
6278
|
+
brightness = 1;
|
|
6279
|
+
} else if (row < rows * 0.6) {
|
|
6280
|
+
brightness = 0.8;
|
|
6281
|
+
} else {
|
|
6282
|
+
brightness = 0.6;
|
|
6283
|
+
}
|
|
6284
|
+
frame[row][col] = brightness;
|
|
6285
|
+
}
|
|
6286
|
+
}
|
|
6287
|
+
}
|
|
6288
|
+
return frame;
|
|
6289
|
+
}
|
|
6290
|
+
var wave = (() => {
|
|
6291
|
+
const frames = [];
|
|
6292
|
+
const rows = 7;
|
|
6293
|
+
const cols = 7;
|
|
6294
|
+
for (let frame = 0; frame < 24; frame++) {
|
|
6295
|
+
const f = emptyFrame(rows, cols);
|
|
6296
|
+
const phase = frame / 24 * Math.PI * 2;
|
|
6297
|
+
for (let col = 0; col < cols; col++) {
|
|
6298
|
+
const colPhase = col / cols * Math.PI * 2;
|
|
6299
|
+
const height = Math.sin(phase + colPhase) * 2.5 + 3.5;
|
|
6300
|
+
const row = Math.floor(height);
|
|
6301
|
+
if (row >= 0 && row < rows) {
|
|
6302
|
+
setPixel(f, row, col, 1);
|
|
6303
|
+
const frac = height - row;
|
|
6304
|
+
if (row > 0) setPixel(f, row - 1, col, 1 - frac);
|
|
6305
|
+
if (row < rows - 1) setPixel(f, row + 1, col, frac);
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
frames.push(f);
|
|
6309
|
+
}
|
|
6310
|
+
return frames;
|
|
6311
|
+
})();
|
|
6312
|
+
var snake = (() => {
|
|
6313
|
+
const frames = [];
|
|
6314
|
+
const rows = 7;
|
|
6315
|
+
const cols = 7;
|
|
6316
|
+
const path = [];
|
|
6317
|
+
let x = 0;
|
|
6318
|
+
let y = 0;
|
|
6319
|
+
let dx = 1;
|
|
6320
|
+
let dy = 0;
|
|
6321
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6322
|
+
while (path.length < rows * cols) {
|
|
6323
|
+
path.push([y, x]);
|
|
6324
|
+
visited.add(`${y},${x}`);
|
|
6325
|
+
const nextX = x + dx;
|
|
6326
|
+
const nextY = y + dy;
|
|
6327
|
+
if (nextX >= 0 && nextX < cols && nextY >= 0 && nextY < rows && !visited.has(`${nextY},${nextX}`)) {
|
|
6328
|
+
x = nextX;
|
|
6329
|
+
y = nextY;
|
|
6330
|
+
} else {
|
|
6331
|
+
const newDx = -dy;
|
|
6332
|
+
const newDy = dx;
|
|
6333
|
+
dx = newDx;
|
|
6334
|
+
dy = newDy;
|
|
6335
|
+
const nextX2 = x + dx;
|
|
6336
|
+
const nextY2 = y + dy;
|
|
6337
|
+
if (nextX2 >= 0 && nextX2 < cols && nextY2 >= 0 && nextY2 < rows && !visited.has(`${nextY2},${nextX2}`)) {
|
|
6338
|
+
x = nextX2;
|
|
6339
|
+
y = nextY2;
|
|
6340
|
+
} else {
|
|
6341
|
+
break;
|
|
6342
|
+
}
|
|
6343
|
+
}
|
|
6344
|
+
}
|
|
6345
|
+
const snakeLength = 5;
|
|
6346
|
+
for (let frame = 0; frame < path.length; frame++) {
|
|
6347
|
+
const f = emptyFrame(rows, cols);
|
|
6348
|
+
for (let i = 0; i < snakeLength; i++) {
|
|
6349
|
+
const idx = frame - i;
|
|
6350
|
+
if (idx >= 0 && idx < path.length) {
|
|
6351
|
+
const [y2, x2] = path[idx];
|
|
6352
|
+
const brightness = 1 - i / snakeLength;
|
|
6353
|
+
setPixel(f, y2, x2, brightness);
|
|
6354
|
+
}
|
|
6355
|
+
}
|
|
6356
|
+
frames.push(f);
|
|
6357
|
+
}
|
|
6358
|
+
return frames;
|
|
6359
|
+
})();
|
|
6360
|
+
var Matrix = React.forwardRef(
|
|
6361
|
+
({
|
|
6362
|
+
rows,
|
|
6363
|
+
cols,
|
|
6364
|
+
pattern,
|
|
6365
|
+
frames,
|
|
6366
|
+
fps = 12,
|
|
6367
|
+
autoplay = true,
|
|
6368
|
+
loop = true,
|
|
6369
|
+
size = 10,
|
|
6370
|
+
gap = 2,
|
|
6371
|
+
palette = {
|
|
6372
|
+
on: "currentColor",
|
|
6373
|
+
off: "var(--muted-foreground)"
|
|
6374
|
+
},
|
|
6375
|
+
brightness = 1,
|
|
6376
|
+
ariaLabel,
|
|
6377
|
+
onFrame,
|
|
6378
|
+
mode = "default",
|
|
6379
|
+
levels,
|
|
6380
|
+
className,
|
|
6381
|
+
...props
|
|
6382
|
+
}, ref) => {
|
|
6383
|
+
const { frameIndex } = useAnimation(frames, {
|
|
6384
|
+
fps,
|
|
6385
|
+
autoplay: autoplay && !pattern,
|
|
6386
|
+
loop,
|
|
6387
|
+
onFrame
|
|
6388
|
+
});
|
|
6389
|
+
const currentFrame = useMemo(() => {
|
|
6390
|
+
if (mode === "vu" && levels && levels.length > 0) {
|
|
6391
|
+
return ensureFrameSize(vu(cols, levels), rows, cols);
|
|
6392
|
+
}
|
|
6393
|
+
if (pattern) {
|
|
6394
|
+
return ensureFrameSize(pattern, rows, cols);
|
|
6395
|
+
}
|
|
6396
|
+
if (frames && frames.length > 0) {
|
|
6397
|
+
return ensureFrameSize(frames[frameIndex] || frames[0], rows, cols);
|
|
6398
|
+
}
|
|
6399
|
+
return ensureFrameSize([], rows, cols);
|
|
6400
|
+
}, [pattern, frames, frameIndex, rows, cols, mode, levels]);
|
|
6401
|
+
const cellPositions = useMemo(() => {
|
|
6402
|
+
const positions = [];
|
|
6403
|
+
for (let row = 0; row < rows; row++) {
|
|
6404
|
+
positions[row] = [];
|
|
6405
|
+
for (let col = 0; col < cols; col++) {
|
|
6406
|
+
positions[row][col] = {
|
|
6407
|
+
x: col * (size + gap),
|
|
6408
|
+
y: row * (size + gap)
|
|
6409
|
+
};
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
return positions;
|
|
6413
|
+
}, [rows, cols, size, gap]);
|
|
6414
|
+
const svgDimensions = useMemo(() => {
|
|
6415
|
+
return {
|
|
6416
|
+
width: cols * (size + gap) - gap,
|
|
6417
|
+
height: rows * (size + gap) - gap
|
|
6418
|
+
};
|
|
6419
|
+
}, [rows, cols, size, gap]);
|
|
6420
|
+
const isAnimating = !pattern && frames && frames.length > 0;
|
|
6421
|
+
return /* @__PURE__ */ jsx(
|
|
6422
|
+
"div",
|
|
6423
|
+
{
|
|
6424
|
+
ref,
|
|
6425
|
+
role: "img",
|
|
6426
|
+
"aria-label": ariaLabel ?? "matrix display",
|
|
6427
|
+
"aria-live": isAnimating ? "polite" : void 0,
|
|
6428
|
+
className: cn("relative inline-block", className),
|
|
6429
|
+
style: {
|
|
6430
|
+
"--matrix-on": palette.on,
|
|
6431
|
+
"--matrix-off": palette.off,
|
|
6432
|
+
"--matrix-gap": `${gap}px`,
|
|
6433
|
+
"--matrix-size": `${size}px`
|
|
6434
|
+
},
|
|
6435
|
+
...props,
|
|
6436
|
+
children: /* @__PURE__ */ jsxs(
|
|
6437
|
+
"svg",
|
|
6438
|
+
{
|
|
6439
|
+
width: svgDimensions.width,
|
|
6440
|
+
height: svgDimensions.height,
|
|
6441
|
+
viewBox: `0 0 ${svgDimensions.width} ${svgDimensions.height}`,
|
|
6442
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6443
|
+
className: "block",
|
|
6444
|
+
style: { overflow: "visible" },
|
|
6445
|
+
children: [
|
|
6446
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
6447
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "matrix-pixel-on", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6448
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "var(--matrix-on)", stopOpacity: "1" }),
|
|
6449
|
+
/* @__PURE__ */ jsx(
|
|
6450
|
+
"stop",
|
|
6451
|
+
{
|
|
6452
|
+
offset: "70%",
|
|
6453
|
+
stopColor: "var(--matrix-on)",
|
|
6454
|
+
stopOpacity: "0.85"
|
|
6455
|
+
}
|
|
6456
|
+
),
|
|
6457
|
+
/* @__PURE__ */ jsx(
|
|
6458
|
+
"stop",
|
|
6459
|
+
{
|
|
6460
|
+
offset: "100%",
|
|
6461
|
+
stopColor: "var(--matrix-on)",
|
|
6462
|
+
stopOpacity: "0.6"
|
|
6463
|
+
}
|
|
6464
|
+
)
|
|
6465
|
+
] }),
|
|
6466
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "matrix-pixel-off", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6467
|
+
/* @__PURE__ */ jsx(
|
|
6468
|
+
"stop",
|
|
6469
|
+
{
|
|
6470
|
+
offset: "0%",
|
|
6471
|
+
stopColor: "var(--muted-foreground)",
|
|
6472
|
+
stopOpacity: "1"
|
|
6473
|
+
}
|
|
6474
|
+
),
|
|
6475
|
+
/* @__PURE__ */ jsx(
|
|
6476
|
+
"stop",
|
|
6477
|
+
{
|
|
6478
|
+
offset: "100%",
|
|
6479
|
+
stopColor: "var(--muted-foreground)",
|
|
6480
|
+
stopOpacity: "0.7"
|
|
6481
|
+
}
|
|
6482
|
+
)
|
|
6483
|
+
] }),
|
|
6484
|
+
/* @__PURE__ */ jsxs(
|
|
6485
|
+
"filter",
|
|
6486
|
+
{
|
|
6487
|
+
id: "matrix-glow",
|
|
6488
|
+
x: "-50%",
|
|
6489
|
+
y: "-50%",
|
|
6490
|
+
width: "200%",
|
|
6491
|
+
height: "200%",
|
|
6492
|
+
children: [
|
|
6493
|
+
/* @__PURE__ */ jsx("feGaussianBlur", { stdDeviation: "2", result: "blur" }),
|
|
6494
|
+
/* @__PURE__ */ jsx("feComposite", { in: "SourceGraphic", in2: "blur", operator: "over" })
|
|
6495
|
+
]
|
|
6496
|
+
}
|
|
6497
|
+
)
|
|
6498
|
+
] }),
|
|
6499
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
6500
|
+
.matrix-pixel {
|
|
6501
|
+
transition: opacity 300ms ease-out, transform 150ms ease-out;
|
|
6502
|
+
transform-origin: center;
|
|
6503
|
+
transform-box: fill-box;
|
|
6504
|
+
}
|
|
6505
|
+
.matrix-pixel-active {
|
|
6506
|
+
filter: url(#matrix-glow);
|
|
6507
|
+
}
|
|
6508
|
+
` }),
|
|
6509
|
+
currentFrame.map(
|
|
6510
|
+
(row, rowIndex) => row.map((value, colIndex) => {
|
|
6511
|
+
const pos = cellPositions[rowIndex]?.[colIndex];
|
|
6512
|
+
if (!pos) return null;
|
|
6513
|
+
const opacity = clamp(brightness * value);
|
|
6514
|
+
const isActive = opacity > 0.5;
|
|
6515
|
+
const isOn = opacity > 0.05;
|
|
6516
|
+
const fill = isOn ? "url(#matrix-pixel-on)" : "url(#matrix-pixel-off)";
|
|
6517
|
+
const scale = isActive ? 1.1 : 1;
|
|
6518
|
+
const radius = size / 2 * 0.9;
|
|
6519
|
+
return /* @__PURE__ */ jsx(
|
|
6520
|
+
"circle",
|
|
6521
|
+
{
|
|
6522
|
+
className: cn(
|
|
6523
|
+
"matrix-pixel",
|
|
6524
|
+
isActive && "matrix-pixel-active",
|
|
6525
|
+
!isOn && "opacity-20 dark:opacity-[0.1]"
|
|
6526
|
+
),
|
|
6527
|
+
cx: pos.x + size / 2,
|
|
6528
|
+
cy: pos.y + size / 2,
|
|
6529
|
+
r: radius,
|
|
6530
|
+
fill,
|
|
6531
|
+
opacity: isOn ? opacity : 0.1,
|
|
6532
|
+
style: {
|
|
6533
|
+
transform: `scale(${scale})`
|
|
6534
|
+
}
|
|
6535
|
+
},
|
|
6536
|
+
`${rowIndex}-${colIndex}`
|
|
6537
|
+
);
|
|
6538
|
+
})
|
|
6539
|
+
)
|
|
6540
|
+
]
|
|
6541
|
+
}
|
|
6542
|
+
)
|
|
6543
|
+
}
|
|
6544
|
+
);
|
|
6545
|
+
}
|
|
6546
|
+
);
|
|
6547
|
+
Matrix.displayName = "Matrix";
|
|
6548
|
+
var DEFAULT_SIZE = 22;
|
|
6549
|
+
var MATRIX_GRID = 7;
|
|
6550
|
+
var MATRIX_ON = "var(--payman-v2-matrix-color)";
|
|
6551
|
+
var MATRIX_PRESETS = [
|
|
6552
|
+
{ frames: loader, fps: 8 },
|
|
6553
|
+
{ frames: wave, fps: 14 },
|
|
6554
|
+
{ frames: snake, fps: 16 },
|
|
6555
|
+
{ frames: pulse, fps: 12 }
|
|
6556
|
+
];
|
|
6557
|
+
var PRESET_ROTATE_MS = 1e4;
|
|
5598
6558
|
function useElapsedSeconds(isStreaming) {
|
|
5599
6559
|
const [elapsed, setElapsed] = useState(0);
|
|
5600
6560
|
const startRef = useRef(null);
|
|
@@ -5615,12 +6575,37 @@ function useElapsedSeconds(isStreaming) {
|
|
|
5615
6575
|
}, [isStreaming]);
|
|
5616
6576
|
return elapsed;
|
|
5617
6577
|
}
|
|
6578
|
+
function useMatrixPresetIndex(isStreaming) {
|
|
6579
|
+
const [index, setIndex] = useState(0);
|
|
6580
|
+
useEffect(() => {
|
|
6581
|
+
if (!isStreaming) return;
|
|
6582
|
+
setIndex(0);
|
|
6583
|
+
const id = setInterval(() => {
|
|
6584
|
+
setIndex((prev) => (prev + 1) % MATRIX_PRESETS.length);
|
|
6585
|
+
}, PRESET_ROTATE_MS);
|
|
6586
|
+
return () => clearInterval(id);
|
|
6587
|
+
}, [isStreaming]);
|
|
6588
|
+
return index;
|
|
6589
|
+
}
|
|
6590
|
+
function formatElapsed(totalSeconds) {
|
|
6591
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
6592
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6593
|
+
const seconds = totalSeconds % 60;
|
|
6594
|
+
return `${minutes}m ${seconds}s`;
|
|
6595
|
+
}
|
|
5618
6596
|
function StreamingIndicatorV2({
|
|
5619
6597
|
isStreaming,
|
|
5620
6598
|
loadingAnimation
|
|
5621
6599
|
}) {
|
|
5622
6600
|
const size = loadingAnimation?.size ?? DEFAULT_SIZE;
|
|
5623
6601
|
const elapsed = useElapsedSeconds(isStreaming);
|
|
6602
|
+
const presetIndex = useMatrixPresetIndex(isStreaming);
|
|
6603
|
+
const preset = MATRIX_PRESETS[presetIndex];
|
|
6604
|
+
const gap = 1;
|
|
6605
|
+
const cell = useMemo(
|
|
6606
|
+
() => Math.max(2, Math.round((size - (MATRIX_GRID - 1) * gap) / MATRIX_GRID)),
|
|
6607
|
+
[size]
|
|
6608
|
+
);
|
|
5624
6609
|
return /* @__PURE__ */ jsx(AnimatePresence, { children: isStreaming && /* @__PURE__ */ jsxs(
|
|
5625
6610
|
motion.div,
|
|
5626
6611
|
{
|
|
@@ -5636,21 +6621,62 @@ function StreamingIndicatorV2({
|
|
|
5636
6621
|
{
|
|
5637
6622
|
className: "payman-v2-streaming-indicator-glyph",
|
|
5638
6623
|
style: { width: size, height: size },
|
|
5639
|
-
children:
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
6624
|
+
children: loadingAnimation?.src ? (
|
|
6625
|
+
// Consumer override: render their Lottie animation.
|
|
6626
|
+
/* @__PURE__ */ jsx(
|
|
6627
|
+
DotLottieReact,
|
|
6628
|
+
{
|
|
6629
|
+
src: loadingAnimation.src,
|
|
6630
|
+
loop: true,
|
|
6631
|
+
autoplay: true,
|
|
6632
|
+
style: { width: "100%", height: "100%" }
|
|
6633
|
+
}
|
|
6634
|
+
)
|
|
6635
|
+
) : (
|
|
6636
|
+
// Default: dot-matrix glyph, cycling presets +
|
|
6637
|
+
// Payman brand tint. Each preset lives in its own
|
|
6638
|
+
// keyed motion layer so swapping presets crossfades
|
|
6639
|
+
// (old scales/fades out while the new scales/fades
|
|
6640
|
+
// in) instead of hard-cutting. Keying the layer on
|
|
6641
|
+
// `presetIndex` also remounts the Matrix, restarting
|
|
6642
|
+
// its frame counter cleanly at frame 0.
|
|
6643
|
+
/* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
|
|
6644
|
+
motion.div,
|
|
6645
|
+
{
|
|
6646
|
+
className: "payman-v2-streaming-indicator-matrix",
|
|
6647
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
6648
|
+
animate: { opacity: 1, scale: 1 },
|
|
6649
|
+
exit: { opacity: 0, scale: 0.8 },
|
|
6650
|
+
transition: { duration: 0.45, ease: [0.2, 0, 0, 1] },
|
|
6651
|
+
children: /* @__PURE__ */ jsx(
|
|
6652
|
+
Matrix,
|
|
6653
|
+
{
|
|
6654
|
+
rows: MATRIX_GRID,
|
|
6655
|
+
cols: MATRIX_GRID,
|
|
6656
|
+
frames: preset.frames,
|
|
6657
|
+
fps: preset.fps,
|
|
6658
|
+
size: cell,
|
|
6659
|
+
gap,
|
|
6660
|
+
palette: {
|
|
6661
|
+
on: MATRIX_ON,
|
|
6662
|
+
// Unlit dots use the v2 theme's own muted-text
|
|
6663
|
+
// token (light/dark-aware), not the bare
|
|
6664
|
+
// `--muted-foreground` the vendored Matrix
|
|
6665
|
+
// component falls back to internally — that
|
|
6666
|
+
// variable isn't defined under `.payman-v2-root`
|
|
6667
|
+
// and would otherwise resolve to black.
|
|
6668
|
+
off: "var(--payman-v2-matrix-dot-off)"
|
|
6669
|
+
},
|
|
6670
|
+
ariaLabel: "Working\u2026"
|
|
6671
|
+
}
|
|
6672
|
+
)
|
|
6673
|
+
},
|
|
6674
|
+
presetIndex
|
|
6675
|
+
) })
|
|
5647
6676
|
)
|
|
5648
6677
|
}
|
|
5649
6678
|
),
|
|
5650
|
-
elapsed > 0 && /* @__PURE__ */
|
|
5651
|
-
elapsed,
|
|
5652
|
-
"s"
|
|
5653
|
-
] })
|
|
6679
|
+
elapsed > 0 && /* @__PURE__ */ jsx("span", { className: "payman-v2-streaming-indicator-elapsed", children: formatElapsed(elapsed) })
|
|
5654
6680
|
]
|
|
5655
6681
|
},
|
|
5656
6682
|
"streaming-indicator"
|
|
@@ -6258,6 +7284,15 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6258
7284
|
const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
|
|
6259
7285
|
const dismissNotification = chat.dismissNotification ?? NOOP;
|
|
6260
7286
|
const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
|
|
7287
|
+
const expiredUserActionIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
7288
|
+
const expireUserActionOnce = useCallback(
|
|
7289
|
+
(userActionId) => {
|
|
7290
|
+
if (expiredUserActionIdsRef.current.has(userActionId)) return;
|
|
7291
|
+
expiredUserActionIdsRef.current.add(userActionId);
|
|
7292
|
+
void expireUserAction2(userActionId);
|
|
7293
|
+
},
|
|
7294
|
+
[expireUserAction2]
|
|
7295
|
+
);
|
|
6261
7296
|
const {
|
|
6262
7297
|
transcribedText,
|
|
6263
7298
|
isAvailable: voiceAvailable,
|
|
@@ -6500,6 +7535,9 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6500
7535
|
};
|
|
6501
7536
|
const userActionPrompts = isUserActionSupported ? userActionState.prompts : void 0;
|
|
6502
7537
|
const notifications = userActionState.notifications;
|
|
7538
|
+
const dockedPrompt = userActionPrompts?.find(
|
|
7539
|
+
(prompt) => prompt.kind !== "notification" && (prompt.status === "pending" || prompt.status === "submitting" || prompt.status === "stale")
|
|
7540
|
+
);
|
|
6503
7541
|
const handleV2Send = (text) => {
|
|
6504
7542
|
if (isRecording) stopRecording();
|
|
6505
7543
|
if (text.trim() && !disableInput && isSessionParamsConfigured) {
|
|
@@ -6652,11 +7690,12 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6652
7690
|
retryDisabled: isWaitingForResponse,
|
|
6653
7691
|
typingSpeed: config.typingSpeed ?? 4,
|
|
6654
7692
|
userActionPrompts,
|
|
7693
|
+
dockedUserActionId: dockedPrompt?.userActionId,
|
|
6655
7694
|
notifications,
|
|
6656
7695
|
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
6657
7696
|
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
6658
7697
|
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
6659
|
-
onExpireUserAction: isUserActionSupported ?
|
|
7698
|
+
onExpireUserAction: isUserActionSupported ? async (id) => expireUserActionOnce(id) : void 0,
|
|
6660
7699
|
onDismissNotification: dismissNotification,
|
|
6661
7700
|
onSubmitFeedback: handleSubmitFeedback
|
|
6662
7701
|
}
|
|
@@ -6669,33 +7708,43 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6669
7708
|
}
|
|
6670
7709
|
),
|
|
6671
7710
|
hasAskPermission && /* @__PURE__ */ jsx(
|
|
6672
|
-
|
|
7711
|
+
UserActionDock,
|
|
6673
7712
|
{
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
onCancel:
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
7713
|
+
prompt: isUserActionSupported ? dockedPrompt : void 0,
|
|
7714
|
+
onSubmit: submitUserAction2,
|
|
7715
|
+
onCancel: cancelUserAction2,
|
|
7716
|
+
onResend: resendUserAction2,
|
|
7717
|
+
onExpired: expireUserActionOnce,
|
|
7718
|
+
children: /* @__PURE__ */ jsx(
|
|
7719
|
+
ChatInputV2,
|
|
7720
|
+
{
|
|
7721
|
+
ref: chatInputV2Ref,
|
|
7722
|
+
onSend: handleV2Send,
|
|
7723
|
+
onCancel: cancelStream,
|
|
7724
|
+
disabled: isV2InputDisabled,
|
|
7725
|
+
isStreaming: isWaitingForResponse,
|
|
7726
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
7727
|
+
enableVoice: config.enableVoice === true,
|
|
7728
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
7729
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
7730
|
+
isRecording,
|
|
7731
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
7732
|
+
onCancelRecording: handleCancelRecording,
|
|
7733
|
+
onConfirmRecording: handleConfirmRecording,
|
|
7734
|
+
showResetSession,
|
|
7735
|
+
onResetSession: requestResetSession,
|
|
7736
|
+
showAttachmentButton,
|
|
7737
|
+
showUploadImageButton,
|
|
7738
|
+
showAttachFileButton,
|
|
7739
|
+
onUploadImageClick,
|
|
7740
|
+
onAttachFileClick,
|
|
7741
|
+
editingMessageId,
|
|
7742
|
+
onClearEditing: handleClearEditing,
|
|
7743
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
7744
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
7745
|
+
slashCommands
|
|
7746
|
+
}
|
|
7747
|
+
)
|
|
6699
7748
|
}
|
|
6700
7749
|
)
|
|
6701
7750
|
]
|