@paymanai/payman-ask-sdk 4.0.26 → 4.0.28
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/README.md +40 -0
- package/dist/index.d.mts +26 -10
- package/dist/index.d.ts +26 -10
- package/dist/index.js +2394 -318
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2392 -317
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +42 -3
- package/dist/index.native.js.map +1 -1
- package/dist/styles.css +714 -1
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { createContext, forwardRef, useCallback, useRef, useState, useMemo, useEffect, useImperativeHandle, useLayoutEffect, useContext } from 'react';
|
|
3
|
-
import { AnimatePresence, motion } from 'framer-motion';
|
|
3
|
+
import { AnimatePresence, motion, useMotionValue, useSpring, useInView } from 'framer-motion';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
import * as Sentry from '@sentry/react';
|
|
7
|
-
import { ArrowDown, Pencil, X, RotateCcw, Telescope, Zap,
|
|
7
|
+
import { ArrowDown, Pencil, X, RotateCcw, Telescope, Zap, ImagePlus, Paperclip, ArrowUp, Check, AlertCircle, Copy, WifiOff, ThumbsUp, ThumbsDown, Binoculars, Info, PanelLeft, Download, Loader2, ChevronDown, MoreHorizontal, User, Clock, Sparkles, ImageOff, Eye, ChevronRight, ShieldCheck } from 'lucide-react';
|
|
8
8
|
import ReactMarkdown from 'react-markdown';
|
|
9
9
|
import remarkGfm from 'remark-gfm';
|
|
10
10
|
import { createPortal } from 'react-dom';
|
|
@@ -1128,6 +1128,9 @@ function getUserActionSecondsLeft(prompt) {
|
|
|
1128
1128
|
return void 0;
|
|
1129
1129
|
}
|
|
1130
1130
|
var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
|
|
1131
|
+
function promptSlotKey(p) {
|
|
1132
|
+
return p.toolCallId || p.userActionId;
|
|
1133
|
+
}
|
|
1131
1134
|
function upsertPrompt(prompts, req) {
|
|
1132
1135
|
const idx = prompts.findIndex(
|
|
1133
1136
|
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
@@ -1174,6 +1177,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1174
1177
|
configRef.current = config;
|
|
1175
1178
|
const messagesRef = useRef(messages);
|
|
1176
1179
|
messagesRef.current = messages;
|
|
1180
|
+
const pendingSubmissionsRef = useRef(/* @__PURE__ */ new Map());
|
|
1177
1181
|
const storeAwareSetMessages = useCallback(
|
|
1178
1182
|
(updater) => {
|
|
1179
1183
|
const streamUserId = streamUserIdRef.current;
|
|
@@ -1208,6 +1212,8 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1208
1212
|
if (!config.userId) return EMPTY_USER_ACTION_STATE2;
|
|
1209
1213
|
return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
|
|
1210
1214
|
});
|
|
1215
|
+
const userActionStateRef = useRef(userActionState);
|
|
1216
|
+
userActionStateRef.current = userActionState;
|
|
1211
1217
|
const storeAwareSetUserActionState = useCallback(
|
|
1212
1218
|
(updater) => {
|
|
1213
1219
|
const streamUserId = streamUserIdRef.current;
|
|
@@ -1235,6 +1241,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1235
1241
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1236
1242
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1237
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
|
+
}
|
|
1238
1250
|
storeAwareSetUserActionState((prev) => ({
|
|
1239
1251
|
...prev,
|
|
1240
1252
|
prompts: upsertPrompt(prev.prompts, request)
|
|
@@ -1246,6 +1258,28 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1246
1258
|
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1247
1259
|
);
|
|
1248
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);
|
|
1249
1283
|
}
|
|
1250
1284
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1251
1285
|
}), []);
|
|
@@ -1381,6 +1415,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1381
1415
|
[storeAwareSetUserActionState]
|
|
1382
1416
|
);
|
|
1383
1417
|
const removePrompt = useCallback((userActionId) => {
|
|
1418
|
+
pendingSubmissionsRef.current.delete(userActionId);
|
|
1384
1419
|
storeAwareSetUserActionState((prev) => ({
|
|
1385
1420
|
...prev,
|
|
1386
1421
|
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
@@ -1391,7 +1426,10 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1391
1426
|
setPromptStatus(userActionId, "submitting");
|
|
1392
1427
|
try {
|
|
1393
1428
|
await submitUserAction(configRef.current, userActionId, content);
|
|
1394
|
-
|
|
1429
|
+
const prompt = userActionStateRef.current.prompts.find(
|
|
1430
|
+
(p) => p.userActionId === userActionId
|
|
1431
|
+
);
|
|
1432
|
+
pendingSubmissionsRef.current.set(userActionId, prompt ? promptSlotKey(prompt) : userActionId);
|
|
1395
1433
|
} catch (error) {
|
|
1396
1434
|
if (error instanceof UserActionStaleError) {
|
|
1397
1435
|
setPromptStatus(userActionId, "stale");
|
|
@@ -1402,7 +1440,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1402
1440
|
throw error;
|
|
1403
1441
|
}
|
|
1404
1442
|
},
|
|
1405
|
-
[
|
|
1443
|
+
[setPromptStatus]
|
|
1406
1444
|
);
|
|
1407
1445
|
const cancelUserAction2 = useCallback(
|
|
1408
1446
|
async (userActionId) => {
|
|
@@ -1756,6 +1794,284 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1756
1794
|
reset
|
|
1757
1795
|
};
|
|
1758
1796
|
}
|
|
1797
|
+
var DEFAULT_PAGE_SIZE = 20;
|
|
1798
|
+
var DEFAULT_MESSAGES_PAGE_SIZE = 100;
|
|
1799
|
+
function defaultParseSessions(json) {
|
|
1800
|
+
const body = json;
|
|
1801
|
+
const rows = Array.isArray(body?.data) ? body.data : [];
|
|
1802
|
+
const data = rows.map((row) => ({ ...row, title: row.title ?? row.sessionTitle ?? null }));
|
|
1803
|
+
return { data, total: body?.total };
|
|
1804
|
+
}
|
|
1805
|
+
function defaultParseMessages(json) {
|
|
1806
|
+
const body = json;
|
|
1807
|
+
return { data: Array.isArray(body?.data) ? body.data : [] };
|
|
1808
|
+
}
|
|
1809
|
+
function withQuery(path, params) {
|
|
1810
|
+
const qs = Object.entries(params).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
|
|
1811
|
+
if (!qs) return path;
|
|
1812
|
+
return `${path}${path.includes("?") ? "&" : "?"}${qs}`;
|
|
1813
|
+
}
|
|
1814
|
+
function toFeedbackState(feedback) {
|
|
1815
|
+
const value = feedback?.feedback;
|
|
1816
|
+
if (!value) return null;
|
|
1817
|
+
return value === "POSITIVE" ? "up" : "down";
|
|
1818
|
+
}
|
|
1819
|
+
function toMessageDisplay(rows, sessionId) {
|
|
1820
|
+
return rows.flatMap((row) => {
|
|
1821
|
+
const timestamp = row.startTime || row.endTime || (/* @__PURE__ */ new Date()).toISOString();
|
|
1822
|
+
const out = [
|
|
1823
|
+
{
|
|
1824
|
+
id: `${row.id}:user`,
|
|
1825
|
+
sessionId,
|
|
1826
|
+
role: "user",
|
|
1827
|
+
content: row.sessionUserIntent,
|
|
1828
|
+
timestamp
|
|
1829
|
+
}
|
|
1830
|
+
];
|
|
1831
|
+
if (row.agentResponse) {
|
|
1832
|
+
out.push({
|
|
1833
|
+
id: `${row.id}:assistant`,
|
|
1834
|
+
sessionId,
|
|
1835
|
+
role: "assistant",
|
|
1836
|
+
content: row.agentResponse,
|
|
1837
|
+
timestamp: row.endTime || timestamp,
|
|
1838
|
+
executionId: row.id,
|
|
1839
|
+
isError: row.status === "FAILED",
|
|
1840
|
+
feedback: toFeedbackState(row.feedback)
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
return out;
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
function useChatSessions({
|
|
1847
|
+
api,
|
|
1848
|
+
sessions,
|
|
1849
|
+
initialSessionId
|
|
1850
|
+
}) {
|
|
1851
|
+
const enabled = sessions?.enabled === true;
|
|
1852
|
+
const listEndpoint = sessions?.listEndpoint ?? "/api/conversations/sessions";
|
|
1853
|
+
const messagesEndpointTemplate = sessions?.messagesEndpoint ?? "/api/conversations/sessions/{sessionId}/messages";
|
|
1854
|
+
const pageSize = sessions?.pageSize ?? DEFAULT_PAGE_SIZE;
|
|
1855
|
+
const messagesPageSize = sessions?.messagesPageSize ?? DEFAULT_MESSAGES_PAGE_SIZE;
|
|
1856
|
+
const parseSessionsResponse = sessions?.parseSessionsResponse ?? defaultParseSessions;
|
|
1857
|
+
const parseMessagesResponse = sessions?.parseMessagesResponse ?? defaultParseMessages;
|
|
1858
|
+
const [sessionsList, setSessionsList] = useState([]);
|
|
1859
|
+
const [isLoadingList, setIsLoadingList] = useState(enabled);
|
|
1860
|
+
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
1861
|
+
const [listError, setListError] = useState(null);
|
|
1862
|
+
const hasLoadedOnceRef = useRef(false);
|
|
1863
|
+
const [page, setPage] = useState(0);
|
|
1864
|
+
const [total, setTotal] = useState(null);
|
|
1865
|
+
const [lastPageFull, setLastPageFull] = useState(false);
|
|
1866
|
+
const [selectedSessionId, setSelectedSessionId] = useState(
|
|
1867
|
+
initialSessionId ?? null
|
|
1868
|
+
);
|
|
1869
|
+
const [draftSessionId, setDraftSessionId] = useState(generateId);
|
|
1870
|
+
const [selectedMessages, setSelectedMessages] = useState([]);
|
|
1871
|
+
const [isLoadingMessages, setIsLoadingMessages] = useState(
|
|
1872
|
+
enabled && initialSessionId != null
|
|
1873
|
+
);
|
|
1874
|
+
const [messagesError, setMessagesError] = useState(null);
|
|
1875
|
+
const [refetchTick, setRefetchTick] = useState(0);
|
|
1876
|
+
const baseUrl = (api.baseUrl || "").replace(/\/+$/, "");
|
|
1877
|
+
const apiHeaders = api.headers;
|
|
1878
|
+
const authToken = api.authToken;
|
|
1879
|
+
const headersKey = JSON.stringify(apiHeaders ?? {});
|
|
1880
|
+
const requestHeaders = useMemo(() => {
|
|
1881
|
+
const headers = { Accept: "application/json", ...apiHeaders ?? {} };
|
|
1882
|
+
if (authToken && !headers.Authorization) headers.Authorization = `Bearer ${authToken}`;
|
|
1883
|
+
return headers;
|
|
1884
|
+
}, [headersKey, authToken]);
|
|
1885
|
+
const hasMore = total != null ? sessionsList.length < total : lastPageFull;
|
|
1886
|
+
useEffect(() => {
|
|
1887
|
+
setPage(0);
|
|
1888
|
+
hasLoadedOnceRef.current = false;
|
|
1889
|
+
}, [enabled, baseUrl, listEndpoint, pageSize, requestHeaders]);
|
|
1890
|
+
useEffect(() => {
|
|
1891
|
+
setPage(0);
|
|
1892
|
+
}, [refetchTick]);
|
|
1893
|
+
useEffect(() => {
|
|
1894
|
+
if (!enabled) return;
|
|
1895
|
+
const ctrl = new AbortController();
|
|
1896
|
+
const isFirstPage = page === 0;
|
|
1897
|
+
if (isFirstPage && !hasLoadedOnceRef.current) setIsLoadingList(true);
|
|
1898
|
+
else if (!isFirstPage) setIsLoadingMore(true);
|
|
1899
|
+
setListError(null);
|
|
1900
|
+
fetch(withQuery(`${baseUrl}${listEndpoint}`, { page, limit: pageSize }), {
|
|
1901
|
+
method: "GET",
|
|
1902
|
+
headers: requestHeaders,
|
|
1903
|
+
signal: ctrl.signal
|
|
1904
|
+
}).then(async (res) => {
|
|
1905
|
+
if (!res.ok) throw new Error(`Failed to load chats (${res.status})`);
|
|
1906
|
+
return res.json();
|
|
1907
|
+
}).then((json) => {
|
|
1908
|
+
const parsed = parseSessionsResponse(json);
|
|
1909
|
+
setSessionsList((prev) => isFirstPage ? parsed.data : [...prev, ...parsed.data]);
|
|
1910
|
+
setTotal(parsed.total ?? null);
|
|
1911
|
+
setLastPageFull(parsed.data.length >= pageSize);
|
|
1912
|
+
hasLoadedOnceRef.current = true;
|
|
1913
|
+
}).catch((e) => {
|
|
1914
|
+
if (e.name === "AbortError") return;
|
|
1915
|
+
setListError(e instanceof Error ? e.message : "Failed to load chats");
|
|
1916
|
+
}).finally(() => {
|
|
1917
|
+
setIsLoadingList(false);
|
|
1918
|
+
setIsLoadingMore(false);
|
|
1919
|
+
});
|
|
1920
|
+
return () => ctrl.abort();
|
|
1921
|
+
}, [enabled, baseUrl, listEndpoint, pageSize, requestHeaders, refetchTick, page]);
|
|
1922
|
+
useEffect(() => {
|
|
1923
|
+
if (!enabled || !selectedSessionId) {
|
|
1924
|
+
setSelectedMessages([]);
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
const ctrl = new AbortController();
|
|
1928
|
+
setIsLoadingMessages(true);
|
|
1929
|
+
setMessagesError(null);
|
|
1930
|
+
const path = messagesEndpointTemplate.replace(
|
|
1931
|
+
"{sessionId}",
|
|
1932
|
+
encodeURIComponent(selectedSessionId)
|
|
1933
|
+
);
|
|
1934
|
+
fetch(withQuery(`${baseUrl}${path}`, { limit: messagesPageSize }), {
|
|
1935
|
+
method: "GET",
|
|
1936
|
+
headers: requestHeaders,
|
|
1937
|
+
signal: ctrl.signal
|
|
1938
|
+
}).then(async (res) => {
|
|
1939
|
+
if (!res.ok) throw new Error(`Failed to load messages (${res.status})`);
|
|
1940
|
+
return res.json();
|
|
1941
|
+
}).then(
|
|
1942
|
+
(json) => setSelectedMessages(
|
|
1943
|
+
toMessageDisplay(parseMessagesResponse(json).data, selectedSessionId)
|
|
1944
|
+
)
|
|
1945
|
+
).catch((e) => {
|
|
1946
|
+
if (e.name === "AbortError") return;
|
|
1947
|
+
setMessagesError(e instanceof Error ? e.message : "Failed to load messages");
|
|
1948
|
+
setSelectedMessages([]);
|
|
1949
|
+
}).finally(() => setIsLoadingMessages(false));
|
|
1950
|
+
return () => ctrl.abort();
|
|
1951
|
+
}, [enabled, selectedSessionId, baseUrl, messagesEndpointTemplate, messagesPageSize, requestHeaders]);
|
|
1952
|
+
const loadMore = useCallback(() => {
|
|
1953
|
+
setPage((prev) => {
|
|
1954
|
+
if (isLoadingList || isLoadingMore || !hasMore) return prev;
|
|
1955
|
+
return prev + 1;
|
|
1956
|
+
});
|
|
1957
|
+
}, [isLoadingList, isLoadingMore, hasMore]);
|
|
1958
|
+
const selectSession = useCallback((sessionId) => {
|
|
1959
|
+
setSelectedSessionId(sessionId);
|
|
1960
|
+
setSelectedMessages([]);
|
|
1961
|
+
}, []);
|
|
1962
|
+
const startNewSession = useCallback(() => {
|
|
1963
|
+
setSelectedSessionId(null);
|
|
1964
|
+
setDraftSessionId(generateId());
|
|
1965
|
+
setSelectedMessages([]);
|
|
1966
|
+
}, []);
|
|
1967
|
+
const refetch = useCallback(() => setRefetchTick((tick) => tick + 1), []);
|
|
1968
|
+
const noteSentMessage = useCallback(
|
|
1969
|
+
(text) => {
|
|
1970
|
+
const id = selectedSessionId ?? draftSessionId;
|
|
1971
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1972
|
+
const trimmed = text.trim();
|
|
1973
|
+
setSessionsList((prev) => {
|
|
1974
|
+
const idx = prev.findIndex((s) => s.sessionId === id);
|
|
1975
|
+
if (idx >= 0) {
|
|
1976
|
+
const existing = prev[idx];
|
|
1977
|
+
const bumped = {
|
|
1978
|
+
...existing,
|
|
1979
|
+
lastMessageAt: now,
|
|
1980
|
+
messageCount: (existing.messageCount ?? 0) + 1,
|
|
1981
|
+
title: existing.title?.trim() ? existing.title : trimmed
|
|
1982
|
+
};
|
|
1983
|
+
return [bumped, ...prev.slice(0, idx), ...prev.slice(idx + 1)];
|
|
1984
|
+
}
|
|
1985
|
+
const fresh = {
|
|
1986
|
+
sessionId: id,
|
|
1987
|
+
title: trimmed,
|
|
1988
|
+
messageCount: 1,
|
|
1989
|
+
lastMessageAt: now,
|
|
1990
|
+
status: "PROCESSING"
|
|
1991
|
+
};
|
|
1992
|
+
return [fresh, ...prev];
|
|
1993
|
+
});
|
|
1994
|
+
},
|
|
1995
|
+
[selectedSessionId, draftSessionId]
|
|
1996
|
+
);
|
|
1997
|
+
return {
|
|
1998
|
+
enabled,
|
|
1999
|
+
sessionsList,
|
|
2000
|
+
isLoadingList,
|
|
2001
|
+
listError,
|
|
2002
|
+
total,
|
|
2003
|
+
hasMore,
|
|
2004
|
+
isLoadingMore,
|
|
2005
|
+
loadMore,
|
|
2006
|
+
noteSentMessage,
|
|
2007
|
+
selectedSessionId,
|
|
2008
|
+
activeSessionId: selectedSessionId ?? draftSessionId,
|
|
2009
|
+
selectSession,
|
|
2010
|
+
startNewSession,
|
|
2011
|
+
selectedMessages,
|
|
2012
|
+
isLoadingMessages,
|
|
2013
|
+
messagesError,
|
|
2014
|
+
refetch
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
function deriveStatus(enabled, blocked) {
|
|
2018
|
+
if (blocked === true) return "blocked";
|
|
2019
|
+
if (enabled === false) return "disabled";
|
|
2020
|
+
if (enabled === true) return "available";
|
|
2021
|
+
return "unknown";
|
|
2022
|
+
}
|
|
2023
|
+
function defaultParse(json) {
|
|
2024
|
+
const body = json;
|
|
2025
|
+
return {
|
|
2026
|
+
available: body?.enabled === true && body?.blocked !== true,
|
|
2027
|
+
status: deriveStatus(body?.enabled, body?.blocked),
|
|
2028
|
+
config: body ?? void 0
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
function useAgentConfig({ api, availability }) {
|
|
2032
|
+
const enabled = availability?.enabled === true;
|
|
2033
|
+
const endpoint = availability?.endpoint ?? "/api/agent/config";
|
|
2034
|
+
const parseResponse = availability?.parseResponse ?? defaultParse;
|
|
2035
|
+
const [available, setAvailable] = useState(null);
|
|
2036
|
+
const [status, setStatus] = useState("unknown");
|
|
2037
|
+
const [config, setConfig] = useState(void 0);
|
|
2038
|
+
const [isLoading, setIsLoading] = useState(enabled);
|
|
2039
|
+
const [error, setError] = useState(null);
|
|
2040
|
+
const [refetchTick, setRefetchTick] = useState(0);
|
|
2041
|
+
const baseUrl = (api.baseUrl || "").replace(/\/+$/, "");
|
|
2042
|
+
const apiHeaders = api.headers;
|
|
2043
|
+
const authToken = api.authToken;
|
|
2044
|
+
const requestHeaders = useMemo(() => {
|
|
2045
|
+
const headers = { Accept: "application/json", ...apiHeaders ?? {} };
|
|
2046
|
+
if (authToken && !headers.Authorization) headers.Authorization = `Bearer ${authToken}`;
|
|
2047
|
+
return headers;
|
|
2048
|
+
}, [apiHeaders, authToken]);
|
|
2049
|
+
useEffect(() => {
|
|
2050
|
+
if (!enabled) return;
|
|
2051
|
+
const ctrl = new AbortController();
|
|
2052
|
+
setIsLoading(true);
|
|
2053
|
+
setError(null);
|
|
2054
|
+
fetch(`${baseUrl}${endpoint}`, {
|
|
2055
|
+
method: "GET",
|
|
2056
|
+
headers: requestHeaders,
|
|
2057
|
+
signal: ctrl.signal
|
|
2058
|
+
}).then(async (res) => {
|
|
2059
|
+
if (!res.ok) throw new Error(`Failed to check availability (${res.status})`);
|
|
2060
|
+
return res.json();
|
|
2061
|
+
}).then((json) => {
|
|
2062
|
+
const parsed = parseResponse(json);
|
|
2063
|
+
setAvailable(parsed.available);
|
|
2064
|
+
setStatus(parsed.status ?? deriveStatus(parsed.available, void 0));
|
|
2065
|
+
setConfig(parsed.config);
|
|
2066
|
+
}).catch((e) => {
|
|
2067
|
+
if (e.name === "AbortError") return;
|
|
2068
|
+
setError(e instanceof Error ? e.message : "Failed to check availability");
|
|
2069
|
+
}).finally(() => setIsLoading(false));
|
|
2070
|
+
return () => ctrl.abort();
|
|
2071
|
+
}, [enabled, baseUrl, endpoint, requestHeaders, refetchTick]);
|
|
2072
|
+
const refetch = useCallback(() => setRefetchTick((tick) => tick + 1), []);
|
|
2073
|
+
return { enabled, available, status, config, isLoading, error, refetch };
|
|
2074
|
+
}
|
|
1759
2075
|
function classifyField(field) {
|
|
1760
2076
|
if (!field) return "text";
|
|
1761
2077
|
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
@@ -3212,11 +3528,10 @@ function UserMessageV2({
|
|
|
3212
3528
|
),
|
|
3213
3529
|
style: { borderRadius: 9999 },
|
|
3214
3530
|
children: [
|
|
3215
|
-
toast.tone === "success" ? /* @__PURE__ */ jsx(Check, {
|
|
3531
|
+
toast.tone === "success" ? /* @__PURE__ */ jsx(Check, { style: { width: 14, height: 14, color: "#059669" } }) : /* @__PURE__ */ jsx(
|
|
3216
3532
|
AlertCircle,
|
|
3217
3533
|
{
|
|
3218
|
-
|
|
3219
|
-
style: { color: "#ef4444" }
|
|
3534
|
+
style: { width: 14, height: 14, color: "#ef4444" }
|
|
3220
3535
|
}
|
|
3221
3536
|
),
|
|
3222
3537
|
/* @__PURE__ */ jsx("span", { children: toast.label })
|
|
@@ -3240,8 +3555,13 @@ function UserMessageV2({
|
|
|
3240
3555
|
/* @__PURE__ */ jsx(
|
|
3241
3556
|
AlertCircle,
|
|
3242
3557
|
{
|
|
3243
|
-
|
|
3244
|
-
|
|
3558
|
+
style: {
|
|
3559
|
+
width: 14,
|
|
3560
|
+
height: 14,
|
|
3561
|
+
flexShrink: 0,
|
|
3562
|
+
color: "rgba(239, 68, 68, 0.7)",
|
|
3563
|
+
marginTop: "2px"
|
|
3564
|
+
}
|
|
3245
3565
|
}
|
|
3246
3566
|
),
|
|
3247
3567
|
/* @__PURE__ */ jsx("p", { className: "payman-v2-user-msg-error-text", children: resolvedError })
|
|
@@ -3259,10 +3579,9 @@ function UserMessageV2({
|
|
|
3259
3579
|
children: copied ? /* @__PURE__ */ jsx(
|
|
3260
3580
|
Check,
|
|
3261
3581
|
{
|
|
3262
|
-
|
|
3263
|
-
style: { color: "#059669" }
|
|
3582
|
+
style: { width: 14, height: 14, color: "#059669" }
|
|
3264
3583
|
}
|
|
3265
|
-
) : /* @__PURE__ */ jsx(Copy, {
|
|
3584
|
+
) : /* @__PURE__ */ jsx(Copy, { style: { width: 14, height: 14 } })
|
|
3266
3585
|
}
|
|
3267
3586
|
) }),
|
|
3268
3587
|
showEditAction && onEdit && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Edit", children: /* @__PURE__ */ jsx(
|
|
@@ -3272,7 +3591,7 @@ function UserMessageV2({
|
|
|
3272
3591
|
onClick: () => onEdit(message.id),
|
|
3273
3592
|
className: "payman-v2-user-msg-action-btn",
|
|
3274
3593
|
"aria-label": "Edit message",
|
|
3275
|
-
children: /* @__PURE__ */ jsx(Pencil, {
|
|
3594
|
+
children: /* @__PURE__ */ jsx(Pencil, { style: { width: 14, height: 14 } })
|
|
3276
3595
|
}
|
|
3277
3596
|
) }),
|
|
3278
3597
|
showRetryAction && onRetry && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Retry", children: /* @__PURE__ */ jsx(
|
|
@@ -3283,7 +3602,7 @@ function UserMessageV2({
|
|
|
3283
3602
|
disabled: retryDisabled,
|
|
3284
3603
|
className: "payman-v2-user-msg-action-btn",
|
|
3285
3604
|
"aria-label": "Retry message",
|
|
3286
|
-
children: /* @__PURE__ */ jsx(RotateCcw, {
|
|
3605
|
+
children: /* @__PURE__ */ jsx(RotateCcw, { style: { width: 14, height: 14 } })
|
|
3287
3606
|
}
|
|
3288
3607
|
) })
|
|
3289
3608
|
] })
|
|
@@ -4082,6 +4401,8 @@ function AssistantMessageV2({
|
|
|
4082
4401
|
void 0,
|
|
4083
4402
|
typingSpeed
|
|
4084
4403
|
);
|
|
4404
|
+
const displayContentPending = Boolean(rawResponseContent) && !displayContent;
|
|
4405
|
+
const showThinkingBlock = isThinkingStreaming || displayContentPending;
|
|
4085
4406
|
const stickyLabel = (() => {
|
|
4086
4407
|
const steps = message.steps;
|
|
4087
4408
|
if (!steps || steps.length === 0) return void 0;
|
|
@@ -4195,14 +4516,12 @@ function AssistantMessageV2({
|
|
|
4195
4516
|
toast.tone === "success" ? /* @__PURE__ */ jsx(
|
|
4196
4517
|
Check,
|
|
4197
4518
|
{
|
|
4198
|
-
|
|
4199
|
-
style: { color: "#059669" }
|
|
4519
|
+
style: { width: 14, height: 14, color: "#059669" }
|
|
4200
4520
|
}
|
|
4201
4521
|
) : /* @__PURE__ */ jsx(
|
|
4202
4522
|
AlertCircle,
|
|
4203
4523
|
{
|
|
4204
|
-
|
|
4205
|
-
style: { color: "#ef4444" }
|
|
4524
|
+
style: { width: 14, height: 14, color: "#ef4444" }
|
|
4206
4525
|
}
|
|
4207
4526
|
),
|
|
4208
4527
|
/* @__PURE__ */ jsx("span", { children: toast.label })
|
|
@@ -4216,7 +4535,7 @@ function AssistantMessageV2({
|
|
|
4216
4535
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4217
4536
|
toastPortal,
|
|
4218
4537
|
/* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: [
|
|
4219
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children:
|
|
4538
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: showThinkingBlock && /* @__PURE__ */ jsx(
|
|
4220
4539
|
motion.div,
|
|
4221
4540
|
{
|
|
4222
4541
|
initial: { opacity: 0, height: 0 },
|
|
@@ -4246,6 +4565,10 @@ function AssistantMessageV2({
|
|
|
4246
4565
|
isResolvingImages: message.isResolvingImages,
|
|
4247
4566
|
onImageClick
|
|
4248
4567
|
}
|
|
4568
|
+
) : displayContentPending ? (
|
|
4569
|
+
// The intent/status line above is still bridging this
|
|
4570
|
+
// gap (see `showThinkingBlock`) — nothing to add here.
|
|
4571
|
+
null
|
|
4249
4572
|
) : !isThinkingStreaming ? /* @__PURE__ */ jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
|
|
4250
4573
|
/* @__PURE__ */ jsx(AnimatePresence, { children: showTrailingProgress && /* @__PURE__ */ jsx(
|
|
4251
4574
|
motion.div,
|
|
@@ -4366,6 +4689,112 @@ function AssistantMessageV2({
|
|
|
4366
4689
|
)
|
|
4367
4690
|
] });
|
|
4368
4691
|
}
|
|
4692
|
+
var CHAR_VARIANTS = {
|
|
4693
|
+
fade: {
|
|
4694
|
+
initial: { opacity: 0, scale: 0.7 },
|
|
4695
|
+
animate: { opacity: 1, scale: 1 },
|
|
4696
|
+
exit: { opacity: 0, scale: 0.7 },
|
|
4697
|
+
transition: { duration: 0.14, ease: "easeOut" },
|
|
4698
|
+
overflow: "hidden"
|
|
4699
|
+
},
|
|
4700
|
+
blur: {
|
|
4701
|
+
initial: { opacity: 0, filter: "blur(8px)", y: -8 },
|
|
4702
|
+
animate: { opacity: 1, filter: "blur(0px)", y: 0 },
|
|
4703
|
+
exit: { opacity: 0, filter: "blur(8px)", y: 8 },
|
|
4704
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
4705
|
+
overflow: "visible"
|
|
4706
|
+
}
|
|
4707
|
+
};
|
|
4708
|
+
function CharSlot({
|
|
4709
|
+
char,
|
|
4710
|
+
charKey,
|
|
4711
|
+
effect
|
|
4712
|
+
}) {
|
|
4713
|
+
if (!/\d/.test(char)) return /* @__PURE__ */ jsx("span", { style: { display: "inline-block" }, children: char });
|
|
4714
|
+
const v = CHAR_VARIANTS[effect];
|
|
4715
|
+
return /* @__PURE__ */ jsx("span", { style: { position: "relative", display: "inline-block", overflow: v.overflow }, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsx(
|
|
4716
|
+
motion.span,
|
|
4717
|
+
{
|
|
4718
|
+
initial: v.initial,
|
|
4719
|
+
animate: v.animate,
|
|
4720
|
+
exit: v.exit,
|
|
4721
|
+
transition: v.transition,
|
|
4722
|
+
style: { display: "inline-block" },
|
|
4723
|
+
children: char
|
|
4724
|
+
},
|
|
4725
|
+
charKey
|
|
4726
|
+
) }) });
|
|
4727
|
+
}
|
|
4728
|
+
function CountUp({
|
|
4729
|
+
to,
|
|
4730
|
+
from = 0,
|
|
4731
|
+
duration = 2,
|
|
4732
|
+
delay = 0,
|
|
4733
|
+
digitEffect = "none",
|
|
4734
|
+
className,
|
|
4735
|
+
startWhen = true,
|
|
4736
|
+
separator = ""
|
|
4737
|
+
}) {
|
|
4738
|
+
const ref = useRef(null);
|
|
4739
|
+
const motionValue = useMotionValue(from);
|
|
4740
|
+
const damping = 20 + 40 * (1 / duration);
|
|
4741
|
+
const stiffness = 100 * (1 / duration);
|
|
4742
|
+
const springValue = useSpring(motionValue, { damping, stiffness });
|
|
4743
|
+
const isInView = useInView(ref, { once: true, margin: "0px" });
|
|
4744
|
+
const decimals = useMemo(() => {
|
|
4745
|
+
const d = (n) => {
|
|
4746
|
+
const s = n.toString();
|
|
4747
|
+
return s.includes(".") ? s.split(".")[1].length : 0;
|
|
4748
|
+
};
|
|
4749
|
+
return Math.max(d(from), d(to));
|
|
4750
|
+
}, [from, to]);
|
|
4751
|
+
const formatValue = useCallback(
|
|
4752
|
+
(latest) => {
|
|
4753
|
+
const formatted = Intl.NumberFormat("en-US", {
|
|
4754
|
+
useGrouping: !!separator,
|
|
4755
|
+
minimumFractionDigits: decimals,
|
|
4756
|
+
maximumFractionDigits: decimals
|
|
4757
|
+
}).format(latest);
|
|
4758
|
+
return separator ? formatted.replace(/,/g, separator) : formatted;
|
|
4759
|
+
},
|
|
4760
|
+
[decimals, separator]
|
|
4761
|
+
);
|
|
4762
|
+
const [chars, setChars] = useState(formatValue(from).split(""));
|
|
4763
|
+
useEffect(() => {
|
|
4764
|
+
if (isInView && startWhen) {
|
|
4765
|
+
const t = setTimeout(() => motionValue.set(to), delay * 1e3);
|
|
4766
|
+
return () => clearTimeout(t);
|
|
4767
|
+
}
|
|
4768
|
+
}, [isInView, startWhen, motionValue, to, delay]);
|
|
4769
|
+
useEffect(() => {
|
|
4770
|
+
const unsub = springValue.on("change", (latest) => {
|
|
4771
|
+
if (digitEffect === "none") {
|
|
4772
|
+
if (ref.current) ref.current.textContent = formatValue(latest);
|
|
4773
|
+
} else {
|
|
4774
|
+
setChars(formatValue(latest).split(""));
|
|
4775
|
+
}
|
|
4776
|
+
});
|
|
4777
|
+
return () => unsub();
|
|
4778
|
+
}, [springValue, formatValue, digitEffect]);
|
|
4779
|
+
if (digitEffect === "none") {
|
|
4780
|
+
return /* @__PURE__ */ jsx("span", { ref, className: cn(className), children: formatValue(from) });
|
|
4781
|
+
}
|
|
4782
|
+
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)) });
|
|
4783
|
+
}
|
|
4784
|
+
function AnimatedDuration({ seconds, className }) {
|
|
4785
|
+
const total = Math.max(0, seconds);
|
|
4786
|
+
const m = Math.floor(total / 60);
|
|
4787
|
+
const s = total % 60;
|
|
4788
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("tabular-nums", className), children: [
|
|
4789
|
+
m > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4790
|
+
/* @__PURE__ */ jsx(CountUp, { to: m, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4791
|
+
"m",
|
|
4792
|
+
" "
|
|
4793
|
+
] }),
|
|
4794
|
+
/* @__PURE__ */ jsx(CountUp, { to: s, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4795
|
+
"s"
|
|
4796
|
+
] });
|
|
4797
|
+
}
|
|
4369
4798
|
var DEFAULT_MAX_LENGTH = 6;
|
|
4370
4799
|
var MAX_SUPPORTED_LENGTH = 12;
|
|
4371
4800
|
var AUTO_FOCUS_DELAY_MS = 250;
|
|
@@ -4492,7 +4921,6 @@ function VerificationInline({
|
|
|
4492
4921
|
useEffect(() => {
|
|
4493
4922
|
if (prompt.subAction === "SubmissionInvalid") {
|
|
4494
4923
|
setErrored(true);
|
|
4495
|
-
setCode("");
|
|
4496
4924
|
lastSubmittedRef.current = null;
|
|
4497
4925
|
}
|
|
4498
4926
|
}, [prompt.subAction, prompt.userActionId]);
|
|
@@ -4571,7 +4999,7 @@ function VerificationInline({
|
|
|
4571
4999
|
/* @__PURE__ */ jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4572
5000
|
/* @__PURE__ */ jsx(ShieldCheck, { className: "payman-v2-ua-icon", size: 15, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4573
5001
|
/* @__PURE__ */ jsx("span", { className: "payman-v2-ua-title", children: "Verification required" }),
|
|
4574
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
5002
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4575
5003
|
] }),
|
|
4576
5004
|
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 }),
|
|
4577
5005
|
stale ? /* @__PURE__ */ jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -4643,6 +5071,228 @@ function VerificationInline({
|
|
|
4643
5071
|
] })
|
|
4644
5072
|
] });
|
|
4645
5073
|
}
|
|
5074
|
+
function AmountFieldV2({
|
|
5075
|
+
id,
|
|
5076
|
+
value,
|
|
5077
|
+
onChange,
|
|
5078
|
+
disabled,
|
|
5079
|
+
className,
|
|
5080
|
+
onEnter
|
|
5081
|
+
}) {
|
|
5082
|
+
const inputRef = useRef(null);
|
|
5083
|
+
const digits = digitsFromValue(value);
|
|
5084
|
+
const display = formatDigits(digits);
|
|
5085
|
+
useLayoutEffect(() => {
|
|
5086
|
+
const el = inputRef.current;
|
|
5087
|
+
if (el && document.activeElement === el) {
|
|
5088
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
5089
|
+
}
|
|
5090
|
+
}, [display]);
|
|
5091
|
+
return /* @__PURE__ */ jsx(
|
|
5092
|
+
"input",
|
|
5093
|
+
{
|
|
5094
|
+
ref: inputRef,
|
|
5095
|
+
id,
|
|
5096
|
+
type: "text",
|
|
5097
|
+
inputMode: "decimal",
|
|
5098
|
+
autoComplete: "off",
|
|
5099
|
+
className,
|
|
5100
|
+
value: display,
|
|
5101
|
+
placeholder: "0.00",
|
|
5102
|
+
disabled,
|
|
5103
|
+
onChange: (e) => {
|
|
5104
|
+
onChange(valueFromDigits(digitsFromDisplay(e.target.value)));
|
|
5105
|
+
},
|
|
5106
|
+
onKeyDown: (e) => {
|
|
5107
|
+
if (e.key === "Enter") {
|
|
5108
|
+
e.preventDefault();
|
|
5109
|
+
onEnter?.();
|
|
5110
|
+
}
|
|
5111
|
+
},
|
|
5112
|
+
onFocus: (e) => {
|
|
5113
|
+
const el = e.currentTarget;
|
|
5114
|
+
requestAnimationFrame(() => el.setSelectionRange(el.value.length, el.value.length));
|
|
5115
|
+
}
|
|
5116
|
+
}
|
|
5117
|
+
);
|
|
5118
|
+
}
|
|
5119
|
+
function digitsFromDisplay(raw) {
|
|
5120
|
+
return raw.replace(/[^0-9]/g, "").replace(/^0+(?=\d)/, "").slice(-9);
|
|
5121
|
+
}
|
|
5122
|
+
function digitsFromValue(value) {
|
|
5123
|
+
const num = Number(value);
|
|
5124
|
+
if (!value || !Number.isFinite(num) || num <= 0) return "";
|
|
5125
|
+
return String(Math.round(num * 100));
|
|
5126
|
+
}
|
|
5127
|
+
function formatDigits(digits) {
|
|
5128
|
+
if (!digits) return "";
|
|
5129
|
+
const padded = digits.padStart(3, "0");
|
|
5130
|
+
const cents = padded.slice(-2);
|
|
5131
|
+
const whole = padded.slice(0, -2).replace(/^0+(?=\d)/, "") || "0";
|
|
5132
|
+
const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
5133
|
+
return `${grouped}.${cents}`;
|
|
5134
|
+
}
|
|
5135
|
+
function valueFromDigits(digits) {
|
|
5136
|
+
if (!digits) return "";
|
|
5137
|
+
return (Number(digits) / 100).toString();
|
|
5138
|
+
}
|
|
5139
|
+
function findRootClassName(el) {
|
|
5140
|
+
const root = el?.closest(".payman-v2-root");
|
|
5141
|
+
return root instanceof HTMLElement ? root.className : "";
|
|
5142
|
+
}
|
|
5143
|
+
var MENU_MAX_HEIGHT = 240;
|
|
5144
|
+
var OPTION_HEIGHT = 34;
|
|
5145
|
+
var VIEWPORT_MARGIN = 8;
|
|
5146
|
+
function SelectFieldV2({
|
|
5147
|
+
id,
|
|
5148
|
+
value,
|
|
5149
|
+
options,
|
|
5150
|
+
onChange,
|
|
5151
|
+
disabled,
|
|
5152
|
+
error,
|
|
5153
|
+
placeholder = "Select\u2026"
|
|
5154
|
+
}) {
|
|
5155
|
+
const triggerRef = useRef(null);
|
|
5156
|
+
const listRef = useRef(null);
|
|
5157
|
+
const [open, setOpen] = useState(false);
|
|
5158
|
+
const [rect, setRect] = useState(null);
|
|
5159
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
5160
|
+
const [rootClassName, setRootClassName] = useState("");
|
|
5161
|
+
const selected = options.find((o) => o.const === value);
|
|
5162
|
+
useLayoutEffect(() => {
|
|
5163
|
+
if (!open) return;
|
|
5164
|
+
const place = () => {
|
|
5165
|
+
const el = triggerRef.current;
|
|
5166
|
+
if (!el) return;
|
|
5167
|
+
const r = el.getBoundingClientRect();
|
|
5168
|
+
const viewportH = window.innerHeight;
|
|
5169
|
+
const estimatedMenuH = Math.min(
|
|
5170
|
+
options.length * OPTION_HEIGHT + VIEWPORT_MARGIN,
|
|
5171
|
+
MENU_MAX_HEIGHT
|
|
5172
|
+
);
|
|
5173
|
+
const spaceBelow = viewportH - r.bottom;
|
|
5174
|
+
const spaceAbove = r.top;
|
|
5175
|
+
const openUp = spaceBelow < estimatedMenuH && spaceAbove > spaceBelow;
|
|
5176
|
+
setRect({ top: r.bottom, bottom: viewportH - r.top, left: r.left, width: r.width, openUp });
|
|
5177
|
+
setRootClassName(findRootClassName(el));
|
|
5178
|
+
};
|
|
5179
|
+
place();
|
|
5180
|
+
window.addEventListener("resize", place);
|
|
5181
|
+
window.addEventListener("scroll", place, true);
|
|
5182
|
+
return () => {
|
|
5183
|
+
window.removeEventListener("resize", place);
|
|
5184
|
+
window.removeEventListener("scroll", place, true);
|
|
5185
|
+
};
|
|
5186
|
+
}, [open, options.length]);
|
|
5187
|
+
useEffect(() => {
|
|
5188
|
+
if (!open) return;
|
|
5189
|
+
setActiveIndex(Math.max(0, options.findIndex((o) => o.const === value)));
|
|
5190
|
+
listRef.current?.focus();
|
|
5191
|
+
}, [open]);
|
|
5192
|
+
useEffect(() => {
|
|
5193
|
+
if (!open) return;
|
|
5194
|
+
const onDocDown = (e) => {
|
|
5195
|
+
const target = e.target;
|
|
5196
|
+
if (triggerRef.current?.contains(target) || listRef.current?.contains(target)) return;
|
|
5197
|
+
setOpen(false);
|
|
5198
|
+
};
|
|
5199
|
+
document.addEventListener("mousedown", onDocDown);
|
|
5200
|
+
return () => document.removeEventListener("mousedown", onDocDown);
|
|
5201
|
+
}, [open]);
|
|
5202
|
+
const commit = (opt) => {
|
|
5203
|
+
onChange(opt.const);
|
|
5204
|
+
setOpen(false);
|
|
5205
|
+
triggerRef.current?.focus();
|
|
5206
|
+
};
|
|
5207
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5208
|
+
/* @__PURE__ */ jsxs(
|
|
5209
|
+
"button",
|
|
5210
|
+
{
|
|
5211
|
+
ref: triggerRef,
|
|
5212
|
+
id,
|
|
5213
|
+
type: "button",
|
|
5214
|
+
disabled,
|
|
5215
|
+
className: cn("payman-v2-ua-select-trigger", error && "payman-v2-ua-input-error"),
|
|
5216
|
+
"aria-haspopup": "listbox",
|
|
5217
|
+
"aria-expanded": open,
|
|
5218
|
+
onClick: () => setOpen((v) => !v),
|
|
5219
|
+
onKeyDown: (e) => {
|
|
5220
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
5221
|
+
e.preventDefault();
|
|
5222
|
+
setOpen(true);
|
|
5223
|
+
}
|
|
5224
|
+
},
|
|
5225
|
+
children: [
|
|
5226
|
+
/* @__PURE__ */ jsx(
|
|
5227
|
+
"span",
|
|
5228
|
+
{
|
|
5229
|
+
className: cn(
|
|
5230
|
+
"payman-v2-ua-select-value",
|
|
5231
|
+
!selected && "payman-v2-ua-select-placeholder"
|
|
5232
|
+
),
|
|
5233
|
+
children: selected ? selected.title || selected.const : placeholder
|
|
5234
|
+
}
|
|
5235
|
+
),
|
|
5236
|
+
/* @__PURE__ */ jsx(ChevronDown, { size: 14, className: "payman-v2-ua-select-chevron", "aria-hidden": true })
|
|
5237
|
+
]
|
|
5238
|
+
}
|
|
5239
|
+
),
|
|
5240
|
+
open && rect && typeof document !== "undefined" && createPortal(
|
|
5241
|
+
/* @__PURE__ */ jsx(
|
|
5242
|
+
"div",
|
|
5243
|
+
{
|
|
5244
|
+
ref: listRef,
|
|
5245
|
+
role: "listbox",
|
|
5246
|
+
className: cn(rootClassName, "payman-v2-ua-select-menu"),
|
|
5247
|
+
tabIndex: -1,
|
|
5248
|
+
style: {
|
|
5249
|
+
position: "fixed",
|
|
5250
|
+
left: rect.left,
|
|
5251
|
+
width: rect.width,
|
|
5252
|
+
height: "fit-content",
|
|
5253
|
+
maxHeight: MENU_MAX_HEIGHT,
|
|
5254
|
+
...rect.openUp ? { bottom: rect.bottom } : { top: rect.top }
|
|
5255
|
+
},
|
|
5256
|
+
onKeyDown: (e) => {
|
|
5257
|
+
if (e.key === "ArrowDown") {
|
|
5258
|
+
e.preventDefault();
|
|
5259
|
+
setActiveIndex((i) => Math.min(options.length - 1, i + 1));
|
|
5260
|
+
} else if (e.key === "ArrowUp") {
|
|
5261
|
+
e.preventDefault();
|
|
5262
|
+
setActiveIndex((i) => Math.max(0, i - 1));
|
|
5263
|
+
} else if (e.key === "Enter" || e.key === " ") {
|
|
5264
|
+
e.preventDefault();
|
|
5265
|
+
if (activeIndex >= 0) commit(options[activeIndex]);
|
|
5266
|
+
} else if (e.key === "Escape" || e.key === "Tab") {
|
|
5267
|
+
setOpen(false);
|
|
5268
|
+
triggerRef.current?.focus();
|
|
5269
|
+
}
|
|
5270
|
+
},
|
|
5271
|
+
children: options.map((opt, i) => /* @__PURE__ */ jsxs(
|
|
5272
|
+
"div",
|
|
5273
|
+
{
|
|
5274
|
+
role: "option",
|
|
5275
|
+
"aria-selected": opt.const === value,
|
|
5276
|
+
className: cn(
|
|
5277
|
+
"payman-v2-ua-select-option",
|
|
5278
|
+
i === activeIndex && "payman-v2-ua-select-option-active",
|
|
5279
|
+
opt.const === value && "payman-v2-ua-select-option-selected"
|
|
5280
|
+
),
|
|
5281
|
+
onMouseEnter: () => setActiveIndex(i),
|
|
5282
|
+
onClick: () => commit(opt),
|
|
5283
|
+
children: [
|
|
5284
|
+
/* @__PURE__ */ jsx("span", { children: opt.title || opt.const }),
|
|
5285
|
+
opt.const === value && /* @__PURE__ */ jsx(Check, { size: 13, "aria-hidden": true })
|
|
5286
|
+
]
|
|
5287
|
+
},
|
|
5288
|
+
opt.const
|
|
5289
|
+
))
|
|
5290
|
+
}
|
|
5291
|
+
),
|
|
5292
|
+
document.body
|
|
5293
|
+
)
|
|
5294
|
+
] });
|
|
5295
|
+
}
|
|
4646
5296
|
function SchemaFormInline({
|
|
4647
5297
|
prompt,
|
|
4648
5298
|
secondsLeft,
|
|
@@ -4688,7 +5338,7 @@ function SchemaFormInline({
|
|
|
4688
5338
|
/* @__PURE__ */ jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4689
5339
|
/* @__PURE__ */ jsx(Pencil, { className: "payman-v2-ua-icon", size: 14, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4690
5340
|
/* @__PURE__ */ jsx("span", { className: "payman-v2-ua-title", children: "Action required" }),
|
|
4691
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
5341
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4692
5342
|
] }),
|
|
4693
5343
|
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 })),
|
|
4694
5344
|
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]) => {
|
|
@@ -4720,26 +5370,33 @@ function SchemaFormInline({
|
|
|
4720
5370
|
required && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-req", children: "*" })
|
|
4721
5371
|
] }),
|
|
4722
5372
|
field.description && /* @__PURE__ */ jsx("span", { className: "payman-v2-ua-hint", children: field.description }),
|
|
4723
|
-
widget === "select" ? /* @__PURE__ */
|
|
4724
|
-
|
|
5373
|
+
widget === "select" ? /* @__PURE__ */ jsx(
|
|
5374
|
+
SelectFieldV2,
|
|
4725
5375
|
{
|
|
4726
5376
|
id: fieldId,
|
|
4727
|
-
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4728
5377
|
value: String(values[key] ?? ""),
|
|
5378
|
+
options: getOptions(field),
|
|
4729
5379
|
disabled: locked,
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
5380
|
+
error: Boolean(err),
|
|
5381
|
+
onChange: (v) => setValue(key, v)
|
|
5382
|
+
}
|
|
5383
|
+
) : widget === "decimal" ? /* @__PURE__ */ jsx(
|
|
5384
|
+
AmountFieldV2,
|
|
5385
|
+
{
|
|
5386
|
+
id: fieldId,
|
|
5387
|
+
value: String(values[key] ?? ""),
|
|
5388
|
+
disabled: locked,
|
|
5389
|
+
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
5390
|
+
onChange: (v) => setValue(key, v),
|
|
5391
|
+
onEnter: handleSubmit
|
|
4735
5392
|
}
|
|
4736
5393
|
) : /* @__PURE__ */ jsx(
|
|
4737
5394
|
"input",
|
|
4738
5395
|
{
|
|
4739
5396
|
id: fieldId,
|
|
4740
|
-
type: widget === "integer"
|
|
4741
|
-
inputMode: widget === "integer" ? "numeric" :
|
|
4742
|
-
step: widget === "
|
|
5397
|
+
type: widget === "integer" ? "number" : "text",
|
|
5398
|
+
inputMode: widget === "integer" ? "numeric" : void 0,
|
|
5399
|
+
step: widget === "integer" ? "1" : void 0,
|
|
4743
5400
|
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4744
5401
|
value: String(values[key] ?? ""),
|
|
4745
5402
|
disabled: locked,
|
|
@@ -4836,12 +5493,16 @@ function UserActionInline({
|
|
|
4836
5493
|
onSubmit,
|
|
4837
5494
|
onCancel,
|
|
4838
5495
|
onResend,
|
|
4839
|
-
onExpired
|
|
5496
|
+
onExpired,
|
|
5497
|
+
suppressExpiredNote
|
|
4840
5498
|
}) {
|
|
4841
5499
|
const [secondsLeft, expired] = useExpiryCountdown(prompt);
|
|
4842
5500
|
useEffect(() => {
|
|
4843
5501
|
if (expired && prompt.kind !== "notification") onExpired?.();
|
|
4844
5502
|
}, [expired, onExpired, prompt.kind]);
|
|
5503
|
+
if (expired && prompt.kind !== "notification" && suppressExpiredNote) {
|
|
5504
|
+
return null;
|
|
5505
|
+
}
|
|
4845
5506
|
let body;
|
|
4846
5507
|
if (expired && prompt.kind !== "notification") {
|
|
4847
5508
|
const note = {
|
|
@@ -4902,6 +5563,9 @@ function getPromptViewKey(prompt) {
|
|
|
4902
5563
|
prompt.message ?? ""
|
|
4903
5564
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4904
5565
|
}
|
|
5566
|
+
function getPromptMountKey(prompt) {
|
|
5567
|
+
return [getPromptSlotKey(prompt), prompt.userActionId].join(PROMPT_KEY_SEPARATOR);
|
|
5568
|
+
}
|
|
4905
5569
|
var MessageListV2 = forwardRef(
|
|
4906
5570
|
function MessageListV22({
|
|
4907
5571
|
messages,
|
|
@@ -4913,6 +5577,7 @@ var MessageListV2 = forwardRef(
|
|
|
4913
5577
|
messageActions,
|
|
4914
5578
|
retryDisabled = false,
|
|
4915
5579
|
userActionPrompts,
|
|
5580
|
+
dockedUserActionId,
|
|
4916
5581
|
notifications,
|
|
4917
5582
|
onSubmitUserAction,
|
|
4918
5583
|
onCancelUserAction,
|
|
@@ -5021,10 +5686,11 @@ var MessageListV2 = forwardRef(
|
|
|
5021
5686
|
}, [userActionPrompts]);
|
|
5022
5687
|
const visibleUserActionPrompts = useMemo(
|
|
5023
5688
|
() => userActionPrompts?.filter((prompt) => {
|
|
5689
|
+
if (prompt.userActionId === dockedUserActionId) return false;
|
|
5024
5690
|
const promptKey = getPromptViewKey(prompt);
|
|
5025
5691
|
return !expiredPromptViewState[promptKey]?.hidden;
|
|
5026
5692
|
}),
|
|
5027
|
-
[expiredPromptViewState, userActionPrompts]
|
|
5693
|
+
[dockedUserActionId, expiredPromptViewState, userActionPrompts]
|
|
5028
5694
|
);
|
|
5029
5695
|
const pinToBottom = useCallback((behavior = "instant") => {
|
|
5030
5696
|
const el = scrollRef.current;
|
|
@@ -5173,7 +5839,7 @@ var MessageListV2 = forwardRef(
|
|
|
5173
5839
|
onResend: onResendUserAction ?? noop,
|
|
5174
5840
|
onExpired: () => handleUserActionExpired(promptKey, prompt.userActionId)
|
|
5175
5841
|
},
|
|
5176
|
-
|
|
5842
|
+
getPromptMountKey(prompt)
|
|
5177
5843
|
);
|
|
5178
5844
|
})
|
|
5179
5845
|
]
|
|
@@ -5205,6 +5871,62 @@ var MessageListV2 = forwardRef(
|
|
|
5205
5871
|
] });
|
|
5206
5872
|
}
|
|
5207
5873
|
);
|
|
5874
|
+
function IconNewChat({ size = 16, className, style }) {
|
|
5875
|
+
return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
5876
|
+
"path",
|
|
5877
|
+
{
|
|
5878
|
+
d: "M11.9991 14.25V12M11.9991 12V9.75M11.9991 12H9.74936M11.9991 12H14.2489M20.9983 12C20.9983 13.2938 20.7253 14.5238 20.2338 15.6356L21 20.9991L16.4039 19.85C15.1019 20.5823 13.5993 21 11.9991 21C7.02906 21 3 16.9706 3 12C3 7.02944 7.02906 3 11.9991 3C16.9692 3 20.9983 7.02944 20.9983 12Z",
|
|
5879
|
+
stroke: "currentColor",
|
|
5880
|
+
strokeWidth: 2,
|
|
5881
|
+
strokeLinecap: "round",
|
|
5882
|
+
strokeLinejoin: "round"
|
|
5883
|
+
}
|
|
5884
|
+
) });
|
|
5885
|
+
}
|
|
5886
|
+
function IconPlus({ size = 16, className, style }) {
|
|
5887
|
+
return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
5888
|
+
"path",
|
|
5889
|
+
{
|
|
5890
|
+
d: "M12.0001 4.7998L12 19.1998M19.2 11.9998L4.80005 11.9998",
|
|
5891
|
+
stroke: "currentColor",
|
|
5892
|
+
strokeWidth: 2,
|
|
5893
|
+
strokeLinecap: "round"
|
|
5894
|
+
}
|
|
5895
|
+
) });
|
|
5896
|
+
}
|
|
5897
|
+
function IconMic({ size = 18, className, style }) {
|
|
5898
|
+
return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
5899
|
+
"path",
|
|
5900
|
+
{
|
|
5901
|
+
d: "M2.49292 13.3764C2.82536 15.6606 3.96908 17.7487 5.71484 19.2588C7.4606 20.7688 9.69168 21.5999 11.9999 21.5999C14.3082 21.5999 16.5393 20.7688 18.285 19.2588C20.0308 17.7487 21.1745 15.6606 21.5069 13.3764M12.0013 2.3999C10.9096 2.3999 9.86265 2.83357 9.09072 3.6055C8.31878 4.37744 7.88512 5.4244 7.88512 6.51608V12.0043C7.88512 13.096 8.31878 14.143 9.09072 14.9149C9.86265 15.6868 10.9096 16.1205 12.0013 16.1205C13.093 16.1205 14.1399 15.6868 14.9119 14.9149C15.6838 14.143 16.1175 13.096 16.1175 12.0043V6.51608C16.1175 5.4244 15.6838 4.37744 14.9119 3.6055C14.1399 2.83357 13.093 2.3999 12.0013 2.3999Z",
|
|
5902
|
+
stroke: "currentColor",
|
|
5903
|
+
strokeWidth: 2,
|
|
5904
|
+
strokeLinecap: "round",
|
|
5905
|
+
strokeLinejoin: "round"
|
|
5906
|
+
}
|
|
5907
|
+
) });
|
|
5908
|
+
}
|
|
5909
|
+
function IconClock({ size = 12, className, style }) {
|
|
5910
|
+
return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 25 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
5911
|
+
"path",
|
|
5912
|
+
{
|
|
5913
|
+
d: "M15.5588 15.1987C16.0827 15.3733 16.649 15.0902 16.8237 14.5662C16.9983 14.0423 16.7152 13.476 16.1912 13.3013L15.5588 15.1987ZM12.5 13.125H11.5C11.5 13.5554 11.7754 13.9376 12.1838 14.0737L12.5 13.125ZM13.5 8.42087C13.5 7.86858 13.0523 7.42087 12.5 7.42087C11.9477 7.42087 11.5 7.86858 11.5 8.42087H13.5ZM16.1912 13.3013L12.8162 12.1763L12.1838 14.0737L15.5588 15.1987L16.1912 13.3013ZM13.5 13.125V8.42087H11.5V13.125H13.5ZM20.5 12C20.5 16.4183 16.9183 20 12.5 20V22C18.0228 22 22.5 17.5228 22.5 12H20.5ZM12.5 20C8.08172 20 4.5 16.4183 4.5 12H2.5C2.5 17.5228 6.97715 22 12.5 22V20ZM4.5 12C4.5 7.58172 8.08172 4 12.5 4V2C6.97715 2 2.5 6.47715 2.5 12H4.5ZM12.5 4C16.9183 4 20.5 7.58172 20.5 12H22.5C22.5 6.47715 18.0228 2 12.5 2V4Z",
|
|
5914
|
+
fill: "currentColor"
|
|
5915
|
+
}
|
|
5916
|
+
) });
|
|
5917
|
+
}
|
|
5918
|
+
function IconMessage({ size = 12, className, style }) {
|
|
5919
|
+
return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
5920
|
+
"path",
|
|
5921
|
+
{
|
|
5922
|
+
d: "M8.39917 8.40002H15.5992M8.39917 13.2H12.5992M21.5992 12C21.5992 13.3801 21.308 14.6921 20.7837 15.878L21.601 21.5991L16.6981 20.3734C15.3091 21.1545 13.7062 21.6 11.9992 21.6C6.69724 21.6 2.39917 17.302 2.39917 12C2.39917 6.69809 6.69724 2.40002 11.9992 2.40002C17.3011 2.40002 21.5992 6.69809 21.5992 12Z",
|
|
5923
|
+
stroke: "currentColor",
|
|
5924
|
+
strokeWidth: 2,
|
|
5925
|
+
strokeLinecap: "round",
|
|
5926
|
+
strokeLinejoin: "round"
|
|
5927
|
+
}
|
|
5928
|
+
) });
|
|
5929
|
+
}
|
|
5208
5930
|
var ChatInputV2 = forwardRef(
|
|
5209
5931
|
function ChatInputV22({
|
|
5210
5932
|
onSend,
|
|
@@ -5595,12 +6317,7 @@ var ChatInputV2 = forwardRef(
|
|
|
5595
6317
|
showActions && "payman-v2-input-attach-btn-active"
|
|
5596
6318
|
),
|
|
5597
6319
|
"aria-label": "Attach",
|
|
5598
|
-
children: /* @__PURE__ */ jsx(
|
|
5599
|
-
Plus,
|
|
5600
|
-
{
|
|
5601
|
-
style: { width: 20, height: 20, strokeWidth: 2 }
|
|
5602
|
-
}
|
|
5603
|
-
)
|
|
6320
|
+
children: /* @__PURE__ */ jsx(IconPlus, { size: 20 })
|
|
5604
6321
|
}
|
|
5605
6322
|
),
|
|
5606
6323
|
/* @__PURE__ */ jsx(AnimatePresence, { children: showActions && /* @__PURE__ */ jsxs(
|
|
@@ -5683,7 +6400,7 @@ var ChatInputV2 = forwardRef(
|
|
|
5683
6400
|
),
|
|
5684
6401
|
"aria-label": isRecording ? "Stop recording" : "Voice input",
|
|
5685
6402
|
children: [
|
|
5686
|
-
/* @__PURE__ */ jsx(
|
|
6403
|
+
/* @__PURE__ */ jsx(IconMic, { size: 18 }),
|
|
5687
6404
|
isRecording && /* @__PURE__ */ jsx("span", { className: "payman-v2-input-mic-indicator" })
|
|
5688
6405
|
]
|
|
5689
6406
|
}
|
|
@@ -5719,66 +6436,577 @@ var ChatInputV2 = forwardRef(
|
|
|
5719
6436
|
] });
|
|
5720
6437
|
}
|
|
5721
6438
|
);
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
var thinking_atom_default = "data:application/zip;base64,UEsDBBQAAAAIAMWrkFzFrMWzUgAAAF4AAAANAAAAbWFuaWZlc3QuanNvbqtWKkstKs7Mz1OyUjJS0lFKT81LLUosyS8C8h1S8kty8ktKMlP14SzdrGIHQz0zPZDaxLzM3MQSoN5iJavoaqXMFKAe38TMPIXgZKApSrWxtQBQSwMEFAAAAAgAxauQXLRghFpXBAAA1RwAABEAAABhL01haW4gU2NlbmUuanNvbu1YWW/jNhD+KwafJVWkqMtPbdEDfdiiQIq+GMZCcei1GvmApLRdGP7v/YYiddqbGNumR4wcomZGHM7B76N0ZLstm7N3Wb6b3a3UTjGHPTw8sLnvsA2bCx/X3811q+qMzY/sAx74stjXda7WeaGqL1alyup9OeNeEnmcnRxWZB9VWbH54sjqj2weOI2bH5+KYibhoirZnONSa0f7AzykGOQYkGP4X2dFpbq13ONx0mTVu6x6bNXZXosf4erI9OLwjwRw7Tv4WWLSP+ALa7I2Rs0RkvkzRhEZQdWz8iHCms48Z54RMEAs2gABkcGRYVFHBqXv8Sh2GBKgRzDNW00SIClag1GzugVNShk5OUd9zxMj4cI/2UhoSdUwVBJpn53EGPMTOd0hh8hAUwuodC1UoVZ1ud+9UjWog+jvb6hIv9D9egxT8aK8kfte5tD5kiTYCfpaqvUPyABb7beH9/57zlUi4zBwE+FnrsyUdDOfC/c+iNVqzVOVKoH06vwLLDsr1Y6q+VZLgX7+dxQDW29SDGmKsVNPr1iLSyB1Bkui0CDGAEdkEmmpeXghQwe/Td0slnRzyDQ5NwdH8L05htXHLGFqIWk0fQ+YPhc9P3+3VpvsoDrSYR9KFNHWpKvWdgfdV998/e3sF2w70Nb35f7pAFNdfn0z49QpNLHDVnqh0FL9IUXU1kG1eZmDO1rYzB06+imrN30/hNG9JmkiPLIVm9flE2ZFuRZoFzf0hIyXzkJfqXcgtLJGCSHyi1SR/URF9pNJYP8b2adeaEwwoqc6AQ2XS+obXTi7bdi6eGmWs8MmXyEN3+UFPaOzQGOdBcQ52BeeDGXqgB3jRNIlirBe7Vs2TYNkXeiGsFtcTS0w3XLPAp8x0MQ86uluEVPse66t9R4ZdbVd88Vw4tNpqTcZIZekEUrFQi/2fAS3hqPIwBMXSIqBp6yqVN1shjHH5NejpvUyOtdZzNyX93lNVfwPn+vGrHjDpiuxSXAvFIHDhSdFRNghvcSPnMQLhKRbo3dbg0bvNgYWsZ4xcz7txuIYrGOfOzz0/JiTUZB4acwdVwiNa43abfVGrbVnMA79fCXG3WGvPdLLlM5nc6czWiBpKFXxq07ptqBOudg7hDI49vRUOAJYuJggZiQDrqFSxA6CMgj2/8PCNqDty6oCjqlViaL8XOb0iC4JjWfU51Xb6CiLunz8CiPop0cnnIb6Ryd7YGpf4bqTUmhPSpSSYXxuSsBtk3ztGkQwPAJS7QevkWdOa2SLNLSn378smfqMTZF0yRzV8Ez4SToNf4i5drmWByfHdk1B5PxGQW+Xgix5jMlhTB5jchlS0CeNOiK74GREQROOGVLQhKFuFHSjoH+CgkSELwM3CrqCgjDJGQoKbhT0pikIH0oE+CAMgOmpF3HAof580grxHaWRdt9opjr9wWUyj6UWHnvSD4yZ1N9pBiIXshuF3Cjktd9izmHo61CIxeSAPpWd/gRQSwECFAAUAAAACADFq5BcxazFs1IAAABeAAAADQAAAAAAAAAAAAAAAAAAAAAAbWFuaWZlc3QuanNvblBLAQIUABQAAAAIAMWrkFy0YIRaVwQAANUcAAARAAAAAAAAAAAAAAAAAH0AAABhL01haW4gU2NlbmUuanNvblBLBQYAAAAAAgACAHoAAAADBQAAAAA=";
|
|
5725
|
-
var DEFAULT_SIZE = 36;
|
|
5726
|
-
function useElapsedSeconds(isStreaming) {
|
|
5727
|
-
const [elapsed, setElapsed] = useState(0);
|
|
5728
|
-
const startRef = useRef(null);
|
|
5729
|
-
useEffect(() => {
|
|
5730
|
-
if (!isStreaming) {
|
|
5731
|
-
startRef.current = null;
|
|
5732
|
-
setElapsed(0);
|
|
5733
|
-
return;
|
|
5734
|
-
}
|
|
5735
|
-
startRef.current = performance.now();
|
|
5736
|
-
setElapsed(0);
|
|
5737
|
-
const id = setInterval(() => {
|
|
5738
|
-
if (startRef.current == null) return;
|
|
5739
|
-
const secs = Math.floor((performance.now() - startRef.current) / 1e3);
|
|
5740
|
-
setElapsed(secs);
|
|
5741
|
-
}, 100);
|
|
5742
|
-
return () => clearInterval(id);
|
|
5743
|
-
}, [isStreaming]);
|
|
5744
|
-
return elapsed;
|
|
6439
|
+
function dockKey(prompt) {
|
|
6440
|
+
return `${prompt.toolCallId || prompt.userActionId}:${prompt.userActionId}`;
|
|
5745
6441
|
}
|
|
5746
|
-
function
|
|
5747
|
-
|
|
5748
|
-
|
|
6442
|
+
function UserActionDock({
|
|
6443
|
+
prompt,
|
|
6444
|
+
onSubmit,
|
|
6445
|
+
onCancel,
|
|
6446
|
+
onResend,
|
|
6447
|
+
onExpired,
|
|
6448
|
+
children
|
|
5749
6449
|
}) {
|
|
5750
|
-
|
|
5751
|
-
const elapsed = useElapsedSeconds(isStreaming);
|
|
5752
|
-
return /* @__PURE__ */ jsx(AnimatePresence, { children: isStreaming && /* @__PURE__ */ jsxs(
|
|
6450
|
+
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(
|
|
5753
6451
|
motion.div,
|
|
5754
6452
|
{
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
6453
|
+
initial: { opacity: 0 },
|
|
6454
|
+
animate: { opacity: 1 },
|
|
6455
|
+
exit: { opacity: 0 },
|
|
6456
|
+
transition: { duration: 0.15 },
|
|
6457
|
+
className: "payman-v2-ua-dock-panel",
|
|
6458
|
+
children: /* @__PURE__ */ jsx(
|
|
6459
|
+
UserActionInline,
|
|
6460
|
+
{
|
|
6461
|
+
prompt,
|
|
6462
|
+
onSubmit,
|
|
6463
|
+
onCancel,
|
|
6464
|
+
onResend,
|
|
6465
|
+
onExpired: () => onExpired?.(prompt.userActionId),
|
|
6466
|
+
suppressExpiredNote: true
|
|
6467
|
+
}
|
|
6468
|
+
)
|
|
6469
|
+
},
|
|
6470
|
+
dockKey(prompt)
|
|
6471
|
+
) : /* @__PURE__ */ jsx(
|
|
6472
|
+
motion.div,
|
|
6473
|
+
{
|
|
6474
|
+
initial: { opacity: 0 },
|
|
6475
|
+
animate: { opacity: 1 },
|
|
6476
|
+
exit: { opacity: 0 },
|
|
6477
|
+
transition: { duration: 0.15 },
|
|
6478
|
+
children
|
|
6479
|
+
},
|
|
6480
|
+
"composer"
|
|
6481
|
+
) }) }) });
|
|
6482
|
+
}
|
|
6483
|
+
function clamp(value) {
|
|
6484
|
+
return Math.max(0, Math.min(1, value));
|
|
6485
|
+
}
|
|
6486
|
+
function ensureFrameSize(frame, rows, cols) {
|
|
6487
|
+
const result = [];
|
|
6488
|
+
for (let r = 0; r < rows; r++) {
|
|
6489
|
+
const row = frame[r] || [];
|
|
6490
|
+
result.push([]);
|
|
6491
|
+
for (let c = 0; c < cols; c++) {
|
|
6492
|
+
result[r][c] = row[c] ?? 0;
|
|
6493
|
+
}
|
|
6494
|
+
}
|
|
6495
|
+
return result;
|
|
6496
|
+
}
|
|
6497
|
+
function useAnimation(frames, options) {
|
|
6498
|
+
const [frameIndex, setFrameIndex] = useState(0);
|
|
6499
|
+
const [isPlaying, setIsPlaying] = useState(options.autoplay);
|
|
6500
|
+
const frameIdRef = useRef(void 0);
|
|
6501
|
+
const lastTimeRef = useRef(0);
|
|
6502
|
+
const accumulatorRef = useRef(0);
|
|
6503
|
+
useEffect(() => {
|
|
6504
|
+
if (!frames || frames.length === 0 || !isPlaying) {
|
|
6505
|
+
return;
|
|
6506
|
+
}
|
|
6507
|
+
const frameInterval = 1e3 / options.fps;
|
|
6508
|
+
const animate = (currentTime) => {
|
|
6509
|
+
if (lastTimeRef.current === 0) {
|
|
6510
|
+
lastTimeRef.current = currentTime;
|
|
6511
|
+
}
|
|
6512
|
+
const deltaTime = currentTime - lastTimeRef.current;
|
|
6513
|
+
lastTimeRef.current = currentTime;
|
|
6514
|
+
accumulatorRef.current += deltaTime;
|
|
6515
|
+
if (accumulatorRef.current >= frameInterval) {
|
|
6516
|
+
accumulatorRef.current -= frameInterval;
|
|
6517
|
+
setFrameIndex((prev) => {
|
|
6518
|
+
const next = prev + 1;
|
|
6519
|
+
if (next >= frames.length) {
|
|
6520
|
+
if (options.loop) {
|
|
6521
|
+
options.onFrame?.(0);
|
|
6522
|
+
return 0;
|
|
6523
|
+
} else {
|
|
6524
|
+
setIsPlaying(false);
|
|
6525
|
+
return prev;
|
|
6526
|
+
}
|
|
6527
|
+
}
|
|
6528
|
+
options.onFrame?.(next);
|
|
6529
|
+
return next;
|
|
6530
|
+
});
|
|
6531
|
+
}
|
|
6532
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6533
|
+
};
|
|
6534
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6535
|
+
return () => {
|
|
6536
|
+
if (frameIdRef.current) {
|
|
6537
|
+
cancelAnimationFrame(frameIdRef.current);
|
|
6538
|
+
}
|
|
6539
|
+
};
|
|
6540
|
+
}, [frames, isPlaying, options.fps, options.loop, options.onFrame]);
|
|
6541
|
+
useEffect(() => {
|
|
6542
|
+
setFrameIndex(0);
|
|
6543
|
+
setIsPlaying(options.autoplay);
|
|
6544
|
+
lastTimeRef.current = 0;
|
|
6545
|
+
accumulatorRef.current = 0;
|
|
6546
|
+
}, [frames, options.autoplay]);
|
|
6547
|
+
return { frameIndex, isPlaying };
|
|
6548
|
+
}
|
|
6549
|
+
function emptyFrame(rows, cols) {
|
|
6550
|
+
return Array.from({ length: rows }, () => Array(cols).fill(0));
|
|
6551
|
+
}
|
|
6552
|
+
function setPixel(frame, row, col, value) {
|
|
6553
|
+
if (row >= 0 && row < frame.length && col >= 0 && col < frame[0].length) {
|
|
6554
|
+
frame[row][col] = value;
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
var loader = (() => {
|
|
6558
|
+
const frames = [];
|
|
6559
|
+
const size = 7;
|
|
6560
|
+
const center = 3;
|
|
6561
|
+
const radius = 2.5;
|
|
6562
|
+
for (let frame = 0; frame < 12; frame++) {
|
|
6563
|
+
const f = emptyFrame(size, size);
|
|
6564
|
+
for (let i = 0; i < 8; i++) {
|
|
6565
|
+
const angle = frame / 12 * Math.PI * 2 + i / 8 * Math.PI * 2;
|
|
6566
|
+
const x = Math.round(center + Math.cos(angle) * radius);
|
|
6567
|
+
const y = Math.round(center + Math.sin(angle) * radius);
|
|
6568
|
+
const brightness = 1 - i / 10;
|
|
6569
|
+
setPixel(f, y, x, Math.max(0.2, brightness));
|
|
6570
|
+
}
|
|
6571
|
+
frames.push(f);
|
|
6572
|
+
}
|
|
6573
|
+
return frames;
|
|
6574
|
+
})();
|
|
6575
|
+
var pulse = (() => {
|
|
6576
|
+
const frames = [];
|
|
6577
|
+
const size = 7;
|
|
6578
|
+
const center = 3;
|
|
6579
|
+
for (let frame = 0; frame < 16; frame++) {
|
|
6580
|
+
const f = emptyFrame(size, size);
|
|
6581
|
+
const phase = frame / 16 * Math.PI * 2;
|
|
6582
|
+
const intensity = (Math.sin(phase) + 1) / 2;
|
|
6583
|
+
setPixel(f, center, center, 1);
|
|
6584
|
+
const radius = Math.floor((1 - intensity) * 3) + 1;
|
|
6585
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
6586
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
6587
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
6588
|
+
if (Math.abs(dist - radius) < 0.7) {
|
|
6589
|
+
setPixel(f, center + dy, center + dx, intensity * 0.6);
|
|
6590
|
+
}
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
frames.push(f);
|
|
6594
|
+
}
|
|
6595
|
+
return frames;
|
|
6596
|
+
})();
|
|
6597
|
+
function vu(columns, levels) {
|
|
6598
|
+
const rows = 7;
|
|
6599
|
+
const frame = emptyFrame(rows, columns);
|
|
6600
|
+
for (let col = 0; col < Math.min(columns, levels.length); col++) {
|
|
6601
|
+
const level = Math.max(0, Math.min(1, levels[col]));
|
|
6602
|
+
const height = Math.floor(level * rows);
|
|
6603
|
+
for (let row = 0; row < rows; row++) {
|
|
6604
|
+
const rowFromBottom = rows - 1 - row;
|
|
6605
|
+
if (rowFromBottom < height) {
|
|
6606
|
+
let brightness = 1;
|
|
6607
|
+
if (row < rows * 0.3) {
|
|
6608
|
+
brightness = 1;
|
|
6609
|
+
} else if (row < rows * 0.6) {
|
|
6610
|
+
brightness = 0.8;
|
|
6611
|
+
} else {
|
|
6612
|
+
brightness = 0.6;
|
|
6613
|
+
}
|
|
6614
|
+
frame[row][col] = brightness;
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
}
|
|
6618
|
+
return frame;
|
|
6619
|
+
}
|
|
6620
|
+
var wave = (() => {
|
|
6621
|
+
const frames = [];
|
|
6622
|
+
const rows = 7;
|
|
6623
|
+
const cols = 7;
|
|
6624
|
+
for (let frame = 0; frame < 24; frame++) {
|
|
6625
|
+
const f = emptyFrame(rows, cols);
|
|
6626
|
+
const phase = frame / 24 * Math.PI * 2;
|
|
6627
|
+
for (let col = 0; col < cols; col++) {
|
|
6628
|
+
const colPhase = col / cols * Math.PI * 2;
|
|
6629
|
+
const height = Math.sin(phase + colPhase) * 2.5 + 3.5;
|
|
6630
|
+
const row = Math.floor(height);
|
|
6631
|
+
if (row >= 0 && row < rows) {
|
|
6632
|
+
setPixel(f, row, col, 1);
|
|
6633
|
+
const frac = height - row;
|
|
6634
|
+
if (row > 0) setPixel(f, row - 1, col, 1 - frac);
|
|
6635
|
+
if (row < rows - 1) setPixel(f, row + 1, col, frac);
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
frames.push(f);
|
|
6639
|
+
}
|
|
6640
|
+
return frames;
|
|
6641
|
+
})();
|
|
6642
|
+
var snake = (() => {
|
|
6643
|
+
const frames = [];
|
|
6644
|
+
const rows = 7;
|
|
6645
|
+
const cols = 7;
|
|
6646
|
+
const path = [];
|
|
6647
|
+
let x = 0;
|
|
6648
|
+
let y = 0;
|
|
6649
|
+
let dx = 1;
|
|
6650
|
+
let dy = 0;
|
|
6651
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6652
|
+
while (path.length < rows * cols) {
|
|
6653
|
+
path.push([y, x]);
|
|
6654
|
+
visited.add(`${y},${x}`);
|
|
6655
|
+
const nextX = x + dx;
|
|
6656
|
+
const nextY = y + dy;
|
|
6657
|
+
if (nextX >= 0 && nextX < cols && nextY >= 0 && nextY < rows && !visited.has(`${nextY},${nextX}`)) {
|
|
6658
|
+
x = nextX;
|
|
6659
|
+
y = nextY;
|
|
6660
|
+
} else {
|
|
6661
|
+
const newDx = -dy;
|
|
6662
|
+
const newDy = dx;
|
|
6663
|
+
dx = newDx;
|
|
6664
|
+
dy = newDy;
|
|
6665
|
+
const nextX2 = x + dx;
|
|
6666
|
+
const nextY2 = y + dy;
|
|
6667
|
+
if (nextX2 >= 0 && nextX2 < cols && nextY2 >= 0 && nextY2 < rows && !visited.has(`${nextY2},${nextX2}`)) {
|
|
6668
|
+
x = nextX2;
|
|
6669
|
+
y = nextY2;
|
|
6670
|
+
} else {
|
|
6671
|
+
break;
|
|
6672
|
+
}
|
|
6673
|
+
}
|
|
6674
|
+
}
|
|
6675
|
+
const snakeLength = 5;
|
|
6676
|
+
for (let frame = 0; frame < path.length; frame++) {
|
|
6677
|
+
const f = emptyFrame(rows, cols);
|
|
6678
|
+
for (let i = 0; i < snakeLength; i++) {
|
|
6679
|
+
const idx = frame - i;
|
|
6680
|
+
if (idx >= 0 && idx < path.length) {
|
|
6681
|
+
const [y2, x2] = path[idx];
|
|
6682
|
+
const brightness = 1 - i / snakeLength;
|
|
6683
|
+
setPixel(f, y2, x2, brightness);
|
|
6684
|
+
}
|
|
6685
|
+
}
|
|
6686
|
+
frames.push(f);
|
|
6687
|
+
}
|
|
6688
|
+
return frames;
|
|
6689
|
+
})();
|
|
6690
|
+
var Matrix = React.forwardRef(
|
|
6691
|
+
({
|
|
6692
|
+
rows,
|
|
6693
|
+
cols,
|
|
6694
|
+
pattern,
|
|
6695
|
+
frames,
|
|
6696
|
+
fps = 12,
|
|
6697
|
+
autoplay = true,
|
|
6698
|
+
loop = true,
|
|
6699
|
+
size = 10,
|
|
6700
|
+
gap = 2,
|
|
6701
|
+
palette = {
|
|
6702
|
+
on: "currentColor",
|
|
6703
|
+
off: "var(--muted-foreground)"
|
|
6704
|
+
},
|
|
6705
|
+
brightness = 1,
|
|
6706
|
+
ariaLabel,
|
|
6707
|
+
onFrame,
|
|
6708
|
+
mode = "default",
|
|
6709
|
+
levels,
|
|
6710
|
+
className,
|
|
6711
|
+
...props
|
|
6712
|
+
}, ref) => {
|
|
6713
|
+
const { frameIndex } = useAnimation(frames, {
|
|
6714
|
+
fps,
|
|
6715
|
+
autoplay: autoplay && !pattern,
|
|
6716
|
+
loop,
|
|
6717
|
+
onFrame
|
|
6718
|
+
});
|
|
6719
|
+
const currentFrame = useMemo(() => {
|
|
6720
|
+
if (mode === "vu" && levels && levels.length > 0) {
|
|
6721
|
+
return ensureFrameSize(vu(cols, levels), rows, cols);
|
|
6722
|
+
}
|
|
6723
|
+
if (pattern) {
|
|
6724
|
+
return ensureFrameSize(pattern, rows, cols);
|
|
6725
|
+
}
|
|
6726
|
+
if (frames && frames.length > 0) {
|
|
6727
|
+
return ensureFrameSize(frames[frameIndex] || frames[0], rows, cols);
|
|
6728
|
+
}
|
|
6729
|
+
return ensureFrameSize([], rows, cols);
|
|
6730
|
+
}, [pattern, frames, frameIndex, rows, cols, mode, levels]);
|
|
6731
|
+
const cellPositions = useMemo(() => {
|
|
6732
|
+
const positions = [];
|
|
6733
|
+
for (let row = 0; row < rows; row++) {
|
|
6734
|
+
positions[row] = [];
|
|
6735
|
+
for (let col = 0; col < cols; col++) {
|
|
6736
|
+
positions[row][col] = {
|
|
6737
|
+
x: col * (size + gap),
|
|
6738
|
+
y: row * (size + gap)
|
|
6739
|
+
};
|
|
6740
|
+
}
|
|
6741
|
+
}
|
|
6742
|
+
return positions;
|
|
6743
|
+
}, [rows, cols, size, gap]);
|
|
6744
|
+
const svgDimensions = useMemo(() => {
|
|
6745
|
+
return {
|
|
6746
|
+
width: cols * (size + gap) - gap,
|
|
6747
|
+
height: rows * (size + gap) - gap
|
|
6748
|
+
};
|
|
6749
|
+
}, [rows, cols, size, gap]);
|
|
6750
|
+
const isAnimating = !pattern && frames && frames.length > 0;
|
|
6751
|
+
return /* @__PURE__ */ jsx(
|
|
6752
|
+
"div",
|
|
6753
|
+
{
|
|
6754
|
+
ref,
|
|
6755
|
+
role: "img",
|
|
6756
|
+
"aria-label": ariaLabel ?? "matrix display",
|
|
6757
|
+
"aria-live": isAnimating ? "polite" : void 0,
|
|
6758
|
+
className: cn("relative inline-block", className),
|
|
6759
|
+
style: {
|
|
6760
|
+
"--matrix-on": palette.on,
|
|
6761
|
+
"--matrix-off": palette.off,
|
|
6762
|
+
"--matrix-gap": `${gap}px`,
|
|
6763
|
+
"--matrix-size": `${size}px`
|
|
6764
|
+
},
|
|
6765
|
+
...props,
|
|
6766
|
+
children: /* @__PURE__ */ jsxs(
|
|
6767
|
+
"svg",
|
|
6768
|
+
{
|
|
6769
|
+
width: svgDimensions.width,
|
|
6770
|
+
height: svgDimensions.height,
|
|
6771
|
+
viewBox: `0 0 ${svgDimensions.width} ${svgDimensions.height}`,
|
|
6772
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6773
|
+
className: "block",
|
|
6774
|
+
style: { overflow: "visible" },
|
|
6775
|
+
children: [
|
|
6776
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
6777
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "matrix-pixel-on", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6778
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "var(--matrix-on)", stopOpacity: "1" }),
|
|
6779
|
+
/* @__PURE__ */ jsx(
|
|
6780
|
+
"stop",
|
|
6781
|
+
{
|
|
6782
|
+
offset: "70%",
|
|
6783
|
+
stopColor: "var(--matrix-on)",
|
|
6784
|
+
stopOpacity: "0.85"
|
|
6785
|
+
}
|
|
6786
|
+
),
|
|
6787
|
+
/* @__PURE__ */ jsx(
|
|
6788
|
+
"stop",
|
|
6789
|
+
{
|
|
6790
|
+
offset: "100%",
|
|
6791
|
+
stopColor: "var(--matrix-on)",
|
|
6792
|
+
stopOpacity: "0.6"
|
|
6793
|
+
}
|
|
6794
|
+
)
|
|
6795
|
+
] }),
|
|
6796
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "matrix-pixel-off", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6797
|
+
/* @__PURE__ */ jsx(
|
|
6798
|
+
"stop",
|
|
6799
|
+
{
|
|
6800
|
+
offset: "0%",
|
|
6801
|
+
stopColor: "var(--muted-foreground)",
|
|
6802
|
+
stopOpacity: "1"
|
|
6803
|
+
}
|
|
6804
|
+
),
|
|
6805
|
+
/* @__PURE__ */ jsx(
|
|
6806
|
+
"stop",
|
|
6807
|
+
{
|
|
6808
|
+
offset: "100%",
|
|
6809
|
+
stopColor: "var(--muted-foreground)",
|
|
6810
|
+
stopOpacity: "0.7"
|
|
6811
|
+
}
|
|
6812
|
+
)
|
|
6813
|
+
] }),
|
|
6814
|
+
/* @__PURE__ */ jsxs(
|
|
6815
|
+
"filter",
|
|
6816
|
+
{
|
|
6817
|
+
id: "matrix-glow",
|
|
6818
|
+
x: "-50%",
|
|
6819
|
+
y: "-50%",
|
|
6820
|
+
width: "200%",
|
|
6821
|
+
height: "200%",
|
|
6822
|
+
children: [
|
|
6823
|
+
/* @__PURE__ */ jsx("feGaussianBlur", { stdDeviation: "2", result: "blur" }),
|
|
6824
|
+
/* @__PURE__ */ jsx("feComposite", { in: "SourceGraphic", in2: "blur", operator: "over" })
|
|
6825
|
+
]
|
|
6826
|
+
}
|
|
6827
|
+
)
|
|
6828
|
+
] }),
|
|
6829
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
6830
|
+
.matrix-pixel {
|
|
6831
|
+
transition: opacity 300ms ease-out, transform 150ms ease-out;
|
|
6832
|
+
transform-origin: center;
|
|
6833
|
+
transform-box: fill-box;
|
|
6834
|
+
}
|
|
6835
|
+
.matrix-pixel-active {
|
|
6836
|
+
filter: url(#matrix-glow);
|
|
6837
|
+
}
|
|
6838
|
+
` }),
|
|
6839
|
+
currentFrame.map(
|
|
6840
|
+
(row, rowIndex) => row.map((value, colIndex) => {
|
|
6841
|
+
const pos = cellPositions[rowIndex]?.[colIndex];
|
|
6842
|
+
if (!pos) return null;
|
|
6843
|
+
const opacity = clamp(brightness * value);
|
|
6844
|
+
const isActive = opacity > 0.5;
|
|
6845
|
+
const isOn = opacity > 0.05;
|
|
6846
|
+
const fill = isOn ? "url(#matrix-pixel-on)" : "url(#matrix-pixel-off)";
|
|
6847
|
+
const scale = isActive ? 1.1 : 1;
|
|
6848
|
+
const radius = size / 2 * 0.9;
|
|
6849
|
+
return /* @__PURE__ */ jsx(
|
|
6850
|
+
"circle",
|
|
6851
|
+
{
|
|
6852
|
+
className: cn(
|
|
6853
|
+
"matrix-pixel",
|
|
6854
|
+
isActive && "matrix-pixel-active",
|
|
6855
|
+
!isOn && "opacity-20 dark:opacity-[0.1]"
|
|
6856
|
+
),
|
|
6857
|
+
cx: pos.x + size / 2,
|
|
6858
|
+
cy: pos.y + size / 2,
|
|
6859
|
+
r: radius,
|
|
6860
|
+
fill,
|
|
6861
|
+
opacity: isOn ? opacity : 0.1,
|
|
6862
|
+
style: {
|
|
6863
|
+
transform: `scale(${scale})`
|
|
6864
|
+
}
|
|
6865
|
+
},
|
|
6866
|
+
`${rowIndex}-${colIndex}`
|
|
6867
|
+
);
|
|
6868
|
+
})
|
|
6869
|
+
)
|
|
6870
|
+
]
|
|
6871
|
+
}
|
|
6872
|
+
)
|
|
6873
|
+
}
|
|
6874
|
+
);
|
|
6875
|
+
}
|
|
6876
|
+
);
|
|
6877
|
+
Matrix.displayName = "Matrix";
|
|
6878
|
+
var DEFAULT_SIZE = 22;
|
|
6879
|
+
var MATRIX_GRID = 7;
|
|
6880
|
+
var MATRIX_ON = "var(--payman-v2-matrix-color)";
|
|
6881
|
+
var MATRIX_PRESETS = [
|
|
6882
|
+
{ frames: loader, fps: 8 },
|
|
6883
|
+
{ frames: wave, fps: 14 },
|
|
6884
|
+
{ frames: snake, fps: 16 },
|
|
6885
|
+
{ frames: pulse, fps: 12 }
|
|
6886
|
+
];
|
|
6887
|
+
var PRESET_ROTATE_MS = 1e4;
|
|
6888
|
+
function useElapsedSeconds(isStreaming) {
|
|
6889
|
+
const [elapsed, setElapsed] = useState(0);
|
|
6890
|
+
const startRef = useRef(null);
|
|
6891
|
+
useEffect(() => {
|
|
6892
|
+
if (!isStreaming) {
|
|
6893
|
+
startRef.current = null;
|
|
6894
|
+
setElapsed(0);
|
|
6895
|
+
return;
|
|
6896
|
+
}
|
|
6897
|
+
startRef.current = performance.now();
|
|
6898
|
+
setElapsed(0);
|
|
6899
|
+
const id = setInterval(() => {
|
|
6900
|
+
if (startRef.current == null) return;
|
|
6901
|
+
const secs = Math.floor((performance.now() - startRef.current) / 1e3);
|
|
6902
|
+
setElapsed(secs);
|
|
6903
|
+
}, 100);
|
|
6904
|
+
return () => clearInterval(id);
|
|
6905
|
+
}, [isStreaming]);
|
|
6906
|
+
return elapsed;
|
|
6907
|
+
}
|
|
6908
|
+
function useMatrixPresetIndex(isStreaming) {
|
|
6909
|
+
const [index, setIndex] = useState(0);
|
|
6910
|
+
useEffect(() => {
|
|
6911
|
+
if (!isStreaming) return;
|
|
6912
|
+
setIndex(0);
|
|
6913
|
+
const id = setInterval(() => {
|
|
6914
|
+
setIndex((prev) => (prev + 1) % MATRIX_PRESETS.length);
|
|
6915
|
+
}, PRESET_ROTATE_MS);
|
|
6916
|
+
return () => clearInterval(id);
|
|
6917
|
+
}, [isStreaming]);
|
|
6918
|
+
return index;
|
|
6919
|
+
}
|
|
6920
|
+
function formatElapsed(totalSeconds) {
|
|
6921
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
6922
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6923
|
+
const seconds = totalSeconds % 60;
|
|
6924
|
+
return `${minutes}m ${seconds}s`;
|
|
6925
|
+
}
|
|
6926
|
+
function StreamingIndicatorV2({
|
|
6927
|
+
isStreaming,
|
|
6928
|
+
loadingAnimation
|
|
6929
|
+
}) {
|
|
6930
|
+
const size = loadingAnimation?.size ?? DEFAULT_SIZE;
|
|
6931
|
+
const elapsed = useElapsedSeconds(isStreaming);
|
|
6932
|
+
const presetIndex = useMatrixPresetIndex(isStreaming);
|
|
6933
|
+
const preset = MATRIX_PRESETS[presetIndex];
|
|
6934
|
+
const gap = 1;
|
|
6935
|
+
const cell = useMemo(
|
|
6936
|
+
() => Math.max(2, Math.round((size - (MATRIX_GRID - 1) * gap) / MATRIX_GRID)),
|
|
6937
|
+
[size]
|
|
6938
|
+
);
|
|
6939
|
+
return /* @__PURE__ */ jsx(AnimatePresence, { children: isStreaming && /* @__PURE__ */ jsxs(
|
|
6940
|
+
motion.div,
|
|
6941
|
+
{
|
|
6942
|
+
className: "payman-v2-streaming-indicator",
|
|
6943
|
+
initial: { opacity: 0, y: 4 },
|
|
6944
|
+
animate: { opacity: 1, y: 0 },
|
|
6945
|
+
exit: { opacity: 0, y: 4 },
|
|
6946
|
+
transition: { duration: 0.2 },
|
|
6947
|
+
"aria-hidden": "true",
|
|
6948
|
+
children: [
|
|
6949
|
+
/* @__PURE__ */ jsx(
|
|
6950
|
+
"div",
|
|
6951
|
+
{
|
|
6952
|
+
className: "payman-v2-streaming-indicator-glyph",
|
|
6953
|
+
style: { width: size, height: size },
|
|
6954
|
+
children: loadingAnimation?.src ? (
|
|
6955
|
+
// Consumer override: render their Lottie animation.
|
|
6956
|
+
/* @__PURE__ */ jsx(
|
|
6957
|
+
DotLottieReact,
|
|
6958
|
+
{
|
|
6959
|
+
src: loadingAnimation.src,
|
|
6960
|
+
loop: true,
|
|
6961
|
+
autoplay: true,
|
|
6962
|
+
style: { width: "100%", height: "100%" }
|
|
6963
|
+
}
|
|
6964
|
+
)
|
|
6965
|
+
) : (
|
|
6966
|
+
// Default: dot-matrix glyph, cycling presets +
|
|
6967
|
+
// Payman brand tint. Each preset lives in its own
|
|
6968
|
+
// keyed motion layer so swapping presets crossfades
|
|
6969
|
+
// (old scales/fades out while the new scales/fades
|
|
6970
|
+
// in) instead of hard-cutting. Keying the layer on
|
|
6971
|
+
// `presetIndex` also remounts the Matrix, restarting
|
|
6972
|
+
// its frame counter cleanly at frame 0.
|
|
6973
|
+
/* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
|
|
6974
|
+
motion.div,
|
|
6975
|
+
{
|
|
6976
|
+
className: "payman-v2-streaming-indicator-matrix",
|
|
6977
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
6978
|
+
animate: { opacity: 1, scale: 1 },
|
|
6979
|
+
exit: { opacity: 0, scale: 0.8 },
|
|
6980
|
+
transition: { duration: 0.45, ease: [0.2, 0, 0, 1] },
|
|
6981
|
+
children: /* @__PURE__ */ jsx(
|
|
6982
|
+
Matrix,
|
|
6983
|
+
{
|
|
6984
|
+
rows: MATRIX_GRID,
|
|
6985
|
+
cols: MATRIX_GRID,
|
|
6986
|
+
frames: preset.frames,
|
|
6987
|
+
fps: preset.fps,
|
|
6988
|
+
size: cell,
|
|
6989
|
+
gap,
|
|
6990
|
+
palette: {
|
|
6991
|
+
on: MATRIX_ON,
|
|
6992
|
+
// Unlit dots use the v2 theme's own muted-text
|
|
6993
|
+
// token (light/dark-aware), not the bare
|
|
6994
|
+
// `--muted-foreground` the vendored Matrix
|
|
6995
|
+
// component falls back to internally — that
|
|
6996
|
+
// variable isn't defined under `.payman-v2-root`
|
|
6997
|
+
// and would otherwise resolve to black.
|
|
6998
|
+
off: "var(--payman-v2-matrix-dot-off)"
|
|
6999
|
+
},
|
|
7000
|
+
ariaLabel: "Working\u2026"
|
|
7001
|
+
}
|
|
7002
|
+
)
|
|
7003
|
+
},
|
|
7004
|
+
presetIndex
|
|
7005
|
+
) })
|
|
5775
7006
|
)
|
|
5776
7007
|
}
|
|
5777
7008
|
),
|
|
5778
|
-
elapsed > 0 && /* @__PURE__ */
|
|
5779
|
-
elapsed,
|
|
5780
|
-
"s"
|
|
5781
|
-
] })
|
|
7009
|
+
elapsed > 0 && /* @__PURE__ */ jsx("span", { className: "payman-v2-streaming-indicator-elapsed", children: formatElapsed(elapsed) })
|
|
5782
7010
|
]
|
|
5783
7011
|
},
|
|
5784
7012
|
"streaming-indicator"
|
|
@@ -6154,82 +7382,660 @@ function TimelineBars({
|
|
|
6154
7382
|
children: /* @__PURE__ */ jsx(
|
|
6155
7383
|
"div",
|
|
6156
7384
|
{
|
|
6157
|
-
style: {
|
|
6158
|
-
height: "100%",
|
|
6159
|
-
width: `${Math.max(widthPct, 0.3)}%`,
|
|
6160
|
-
background: stepColor(step2),
|
|
6161
|
-
transition: "width 0.2s ease"
|
|
6162
|
-
}
|
|
7385
|
+
style: {
|
|
7386
|
+
height: "100%",
|
|
7387
|
+
width: `${Math.max(widthPct, 0.3)}%`,
|
|
7388
|
+
background: stepColor(step2),
|
|
7389
|
+
transition: "width 0.2s ease"
|
|
7390
|
+
}
|
|
7391
|
+
}
|
|
7392
|
+
)
|
|
7393
|
+
}
|
|
7394
|
+
)
|
|
7395
|
+
] }, `${step2.step}-${step2.startTime}`);
|
|
7396
|
+
});
|
|
7397
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
7398
|
+
bars,
|
|
7399
|
+
unaccountedMs > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: 8 }, children: [
|
|
7400
|
+
/* @__PURE__ */ jsxs(
|
|
7401
|
+
"div",
|
|
7402
|
+
{
|
|
7403
|
+
style: {
|
|
7404
|
+
display: "flex",
|
|
7405
|
+
justifyContent: "space-between",
|
|
7406
|
+
fontSize: 12,
|
|
7407
|
+
marginBottom: 4,
|
|
7408
|
+
fontFamily: "ui-monospace, SFMono-Regular, monospace",
|
|
7409
|
+
opacity: 0.7
|
|
7410
|
+
},
|
|
7411
|
+
children: [
|
|
7412
|
+
/* @__PURE__ */ jsx("span", { children: "(unaccounted)" }),
|
|
7413
|
+
/* @__PURE__ */ jsx("span", { children: formatMs(unaccountedMs) })
|
|
7414
|
+
]
|
|
7415
|
+
}
|
|
7416
|
+
),
|
|
7417
|
+
/* @__PURE__ */ jsx(
|
|
7418
|
+
"div",
|
|
7419
|
+
{
|
|
7420
|
+
style: {
|
|
7421
|
+
height: 8,
|
|
7422
|
+
background: "rgba(255,255,255,0.06)",
|
|
7423
|
+
borderRadius: 4,
|
|
7424
|
+
overflow: "hidden"
|
|
7425
|
+
},
|
|
7426
|
+
children: /* @__PURE__ */ jsx(
|
|
7427
|
+
"div",
|
|
7428
|
+
{
|
|
7429
|
+
style: {
|
|
7430
|
+
height: "100%",
|
|
7431
|
+
width: `${unaccountedMs / Math.max(totalMs, 1) * 100}%`,
|
|
7432
|
+
background: "repeating-linear-gradient(45deg, rgba(255,255,255,0.18) 0 4px, transparent 4px 8px)"
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7435
|
+
)
|
|
7436
|
+
}
|
|
7437
|
+
)
|
|
7438
|
+
] }),
|
|
7439
|
+
/* @__PURE__ */ jsxs(
|
|
7440
|
+
"div",
|
|
7441
|
+
{
|
|
7442
|
+
style: {
|
|
7443
|
+
marginTop: 14,
|
|
7444
|
+
paddingTop: 12,
|
|
7445
|
+
borderTop: "1px solid rgba(255,255,255,0.08)",
|
|
7446
|
+
fontSize: 12,
|
|
7447
|
+
display: "flex",
|
|
7448
|
+
justifyContent: "space-between",
|
|
7449
|
+
opacity: 0.85
|
|
7450
|
+
},
|
|
7451
|
+
children: [
|
|
7452
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
7453
|
+
trace.pipelineSteps.length,
|
|
7454
|
+
" step",
|
|
7455
|
+
trace.pipelineSteps.length === 1 ? "" : "s"
|
|
7456
|
+
] }),
|
|
7457
|
+
/* @__PURE__ */ jsxs("span", { style: { fontFamily: "ui-monospace, SFMono-Regular, monospace" }, children: [
|
|
7458
|
+
"total: ",
|
|
7459
|
+
formatMs(totalMs)
|
|
7460
|
+
] })
|
|
7461
|
+
]
|
|
7462
|
+
}
|
|
7463
|
+
)
|
|
7464
|
+
] });
|
|
7465
|
+
}
|
|
7466
|
+
var MIN_SIDEBAR_WIDTH = 240;
|
|
7467
|
+
var MAX_SIDEBAR_WIDTH = 520;
|
|
7468
|
+
var DEFAULT_SIDEBAR_WIDTH = 264;
|
|
7469
|
+
var WIDTH_STORAGE_KEY = "payman-v2-sessions-width";
|
|
7470
|
+
function readStoredWidth() {
|
|
7471
|
+
if (typeof window === "undefined") return DEFAULT_SIDEBAR_WIDTH;
|
|
7472
|
+
const raw = Number(window.localStorage?.getItem(WIDTH_STORAGE_KEY));
|
|
7473
|
+
if (Number.isFinite(raw) && raw >= MIN_SIDEBAR_WIDTH && raw <= MAX_SIDEBAR_WIDTH) return raw;
|
|
7474
|
+
return DEFAULT_SIDEBAR_WIDTH;
|
|
7475
|
+
}
|
|
7476
|
+
function formatRelativeTime(iso) {
|
|
7477
|
+
if (!iso) return "";
|
|
7478
|
+
const date = new Date(iso);
|
|
7479
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
7480
|
+
const diffSec = Math.round((Date.now() - date.getTime()) / 1e3);
|
|
7481
|
+
if (diffSec < 60) return "just now";
|
|
7482
|
+
const diffMin = Math.round(diffSec / 60);
|
|
7483
|
+
if (diffMin < 60) return `${diffMin} minute${diffMin === 1 ? "" : "s"} ago`;
|
|
7484
|
+
const diffHr = Math.round(diffMin / 60);
|
|
7485
|
+
if (diffHr < 24) return `${diffHr} hour${diffHr === 1 ? "" : "s"} ago`;
|
|
7486
|
+
const diffDay = Math.round(diffHr / 24);
|
|
7487
|
+
if (diffDay < 7) return `${diffDay} day${diffDay === 1 ? "" : "s"} ago`;
|
|
7488
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
7489
|
+
}
|
|
7490
|
+
function SessionsSidebarV2({
|
|
7491
|
+
open,
|
|
7492
|
+
onClose,
|
|
7493
|
+
title,
|
|
7494
|
+
newChatLabel,
|
|
7495
|
+
sessions,
|
|
7496
|
+
isLoading,
|
|
7497
|
+
error,
|
|
7498
|
+
onRetry,
|
|
7499
|
+
selectedSessionId,
|
|
7500
|
+
onSelectSession,
|
|
7501
|
+
onNewSession,
|
|
7502
|
+
actions,
|
|
7503
|
+
hasMore,
|
|
7504
|
+
isLoadingMore,
|
|
7505
|
+
onLoadMore
|
|
7506
|
+
}) {
|
|
7507
|
+
const [width, setWidth] = useState(readStoredWidth);
|
|
7508
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
7509
|
+
const dragState = useRef(null);
|
|
7510
|
+
const onResizeMove = useCallback((event) => {
|
|
7511
|
+
if (!dragState.current) return;
|
|
7512
|
+
const delta = event.clientX - dragState.current.startX;
|
|
7513
|
+
const next = Math.min(
|
|
7514
|
+
MAX_SIDEBAR_WIDTH,
|
|
7515
|
+
Math.max(MIN_SIDEBAR_WIDTH, dragState.current.startWidth + delta)
|
|
7516
|
+
);
|
|
7517
|
+
setWidth(next);
|
|
7518
|
+
}, []);
|
|
7519
|
+
const onResizeEnd = useCallback(() => {
|
|
7520
|
+
dragState.current = null;
|
|
7521
|
+
setIsResizing(false);
|
|
7522
|
+
document.removeEventListener("mousemove", onResizeMove);
|
|
7523
|
+
document.removeEventListener("mouseup", onResizeEnd);
|
|
7524
|
+
document.body.style.removeProperty("user-select");
|
|
7525
|
+
setWidth((w) => {
|
|
7526
|
+
if (typeof window !== "undefined") window.localStorage?.setItem(WIDTH_STORAGE_KEY, String(w));
|
|
7527
|
+
return w;
|
|
7528
|
+
});
|
|
7529
|
+
}, [onResizeMove]);
|
|
7530
|
+
const onResizeStart = useCallback(
|
|
7531
|
+
(event) => {
|
|
7532
|
+
event.preventDefault();
|
|
7533
|
+
dragState.current = { startX: event.clientX, startWidth: width };
|
|
7534
|
+
setIsResizing(true);
|
|
7535
|
+
document.body.style.userSelect = "none";
|
|
7536
|
+
document.addEventListener("mousemove", onResizeMove);
|
|
7537
|
+
document.addEventListener("mouseup", onResizeEnd);
|
|
7538
|
+
},
|
|
7539
|
+
[width, onResizeMove, onResizeEnd]
|
|
7540
|
+
);
|
|
7541
|
+
useEffect(
|
|
7542
|
+
() => () => {
|
|
7543
|
+
document.removeEventListener("mousemove", onResizeMove);
|
|
7544
|
+
document.removeEventListener("mouseup", onResizeEnd);
|
|
7545
|
+
},
|
|
7546
|
+
[onResizeMove, onResizeEnd]
|
|
7547
|
+
);
|
|
7548
|
+
return /* @__PURE__ */ jsxs(
|
|
7549
|
+
"div",
|
|
7550
|
+
{
|
|
7551
|
+
className: cn(
|
|
7552
|
+
"payman-v2-sessions-sidebar",
|
|
7553
|
+
!open && "payman-v2-sessions-sidebar-collapsed",
|
|
7554
|
+
isResizing && "payman-v2-sessions-sidebar-resizing"
|
|
7555
|
+
),
|
|
7556
|
+
role: "complementary",
|
|
7557
|
+
"aria-label": title,
|
|
7558
|
+
"aria-hidden": !open,
|
|
7559
|
+
style: { "--payman-v2-sessions-width": `${width}px` },
|
|
7560
|
+
children: [
|
|
7561
|
+
/* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-sidebar-inner", children: [
|
|
7562
|
+
/* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-header", children: [
|
|
7563
|
+
/* @__PURE__ */ jsx("span", { className: "payman-v2-sessions-title", children: title }),
|
|
7564
|
+
onClose && /* @__PURE__ */ jsx(
|
|
7565
|
+
"button",
|
|
7566
|
+
{
|
|
7567
|
+
type: "button",
|
|
7568
|
+
className: "payman-v2-sessions-close",
|
|
7569
|
+
onClick: onClose,
|
|
7570
|
+
"aria-label": "Close chats panel",
|
|
7571
|
+
tabIndex: open ? 0 : -1,
|
|
7572
|
+
children: /* @__PURE__ */ jsx(X, { size: 16 })
|
|
7573
|
+
}
|
|
7574
|
+
)
|
|
7575
|
+
] }),
|
|
7576
|
+
/* @__PURE__ */ jsxs(
|
|
7577
|
+
"button",
|
|
7578
|
+
{
|
|
7579
|
+
type: "button",
|
|
7580
|
+
className: "payman-v2-sessions-new-btn",
|
|
7581
|
+
onClick: onNewSession,
|
|
7582
|
+
tabIndex: open ? 0 : -1,
|
|
7583
|
+
children: [
|
|
7584
|
+
/* @__PURE__ */ jsx(IconNewChat, { size: 16 }),
|
|
7585
|
+
newChatLabel
|
|
7586
|
+
]
|
|
7587
|
+
}
|
|
7588
|
+
),
|
|
7589
|
+
/* @__PURE__ */ jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
7590
|
+
/* @__PURE__ */ jsx(
|
|
7591
|
+
SessionsListBody,
|
|
7592
|
+
{
|
|
7593
|
+
sessions,
|
|
7594
|
+
isLoading,
|
|
7595
|
+
error,
|
|
7596
|
+
onRetry,
|
|
7597
|
+
selectedSessionId,
|
|
7598
|
+
onSelectSession,
|
|
7599
|
+
actions,
|
|
7600
|
+
hasMore,
|
|
7601
|
+
isLoadingMore,
|
|
7602
|
+
onLoadMore
|
|
7603
|
+
}
|
|
7604
|
+
)
|
|
7605
|
+
] }),
|
|
7606
|
+
open && /* @__PURE__ */ jsx(
|
|
7607
|
+
"div",
|
|
7608
|
+
{
|
|
7609
|
+
className: "payman-v2-sessions-resizer",
|
|
7610
|
+
onMouseDown: onResizeStart,
|
|
7611
|
+
role: "separator",
|
|
7612
|
+
"aria-orientation": "vertical",
|
|
7613
|
+
"aria-label": "Resize chats panel"
|
|
7614
|
+
}
|
|
7615
|
+
)
|
|
7616
|
+
]
|
|
7617
|
+
}
|
|
7618
|
+
);
|
|
7619
|
+
}
|
|
7620
|
+
function SessionsListBody({
|
|
7621
|
+
sessions,
|
|
7622
|
+
isLoading,
|
|
7623
|
+
error,
|
|
7624
|
+
onRetry,
|
|
7625
|
+
selectedSessionId,
|
|
7626
|
+
onSelectSession,
|
|
7627
|
+
actions,
|
|
7628
|
+
compact = false,
|
|
7629
|
+
hasMore,
|
|
7630
|
+
isLoadingMore,
|
|
7631
|
+
onLoadMore
|
|
7632
|
+
}) {
|
|
7633
|
+
const [openMenuId, setOpenMenuId] = useState(null);
|
|
7634
|
+
const listRef = useRef(null);
|
|
7635
|
+
const [shadow, setShadow] = useState({ top: false, bottom: false });
|
|
7636
|
+
const updateShadow = useCallback(() => {
|
|
7637
|
+
const el = listRef.current;
|
|
7638
|
+
if (!el) return;
|
|
7639
|
+
const top = el.scrollTop > 1;
|
|
7640
|
+
const bottom = Math.ceil(el.scrollTop + el.clientHeight) < el.scrollHeight - 1;
|
|
7641
|
+
setShadow((s) => s.top === top && s.bottom === bottom ? s : { top, bottom });
|
|
7642
|
+
}, []);
|
|
7643
|
+
useEffect(() => {
|
|
7644
|
+
updateShadow();
|
|
7645
|
+
const el = listRef.current;
|
|
7646
|
+
if (!el) return;
|
|
7647
|
+
const ro = new ResizeObserver(updateShadow);
|
|
7648
|
+
ro.observe(el);
|
|
7649
|
+
return () => ro.disconnect();
|
|
7650
|
+
}, [sessions, isLoading, updateShadow]);
|
|
7651
|
+
return /* @__PURE__ */ jsx(
|
|
7652
|
+
"div",
|
|
7653
|
+
{
|
|
7654
|
+
className: cn(
|
|
7655
|
+
"payman-v2-sessions-list-wrap",
|
|
7656
|
+
shadow.top && "payman-v2-scroll-shadow-top",
|
|
7657
|
+
shadow.bottom && "payman-v2-scroll-shadow-bottom"
|
|
7658
|
+
),
|
|
7659
|
+
children: /* @__PURE__ */ jsx(
|
|
7660
|
+
"div",
|
|
7661
|
+
{
|
|
7662
|
+
ref: listRef,
|
|
7663
|
+
onScroll: updateShadow,
|
|
7664
|
+
className: cn("payman-v2-sessions-list", compact && "payman-v2-sessions-list-compact"),
|
|
7665
|
+
children: isLoading ? /* @__PURE__ */ jsx(SessionsListSkeleton, {}) : error ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-error", children: [
|
|
7666
|
+
/* @__PURE__ */ jsx(AlertCircle, { size: 18 }),
|
|
7667
|
+
/* @__PURE__ */ jsx("p", { children: error }),
|
|
7668
|
+
onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "payman-v2-sessions-retry-btn", onClick: onRetry, children: "Try again" })
|
|
7669
|
+
] }) : sessions.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-empty", children: [
|
|
7670
|
+
/* @__PURE__ */ jsx(IconMessage, { size: 20 }),
|
|
7671
|
+
/* @__PURE__ */ jsx("p", { children: "No chats yet" })
|
|
7672
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7673
|
+
sessions.map((session) => /* @__PURE__ */ jsx(
|
|
7674
|
+
SessionRow,
|
|
7675
|
+
{
|
|
7676
|
+
session,
|
|
7677
|
+
isSelected: session.sessionId === selectedSessionId,
|
|
7678
|
+
isMenuOpen: openMenuId === session.sessionId,
|
|
7679
|
+
onSelect: () => onSelectSession(session.sessionId),
|
|
7680
|
+
onToggleMenu: () => setOpenMenuId((id) => id === session.sessionId ? null : session.sessionId),
|
|
7681
|
+
onCloseMenu: () => setOpenMenuId(null),
|
|
7682
|
+
actions
|
|
7683
|
+
},
|
|
7684
|
+
session.sessionId
|
|
7685
|
+
)),
|
|
7686
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsx(
|
|
7687
|
+
"button",
|
|
7688
|
+
{
|
|
7689
|
+
type: "button",
|
|
7690
|
+
className: "payman-v2-sessions-load-more-btn",
|
|
7691
|
+
onClick: onLoadMore,
|
|
7692
|
+
disabled: isLoadingMore,
|
|
7693
|
+
children: isLoadingMore ? /* @__PURE__ */ jsx("span", { className: "payman-v2-spinner payman-v2-spinner-sm" }) : "Load more"
|
|
7694
|
+
}
|
|
7695
|
+
)
|
|
7696
|
+
] })
|
|
7697
|
+
}
|
|
7698
|
+
)
|
|
7699
|
+
}
|
|
7700
|
+
);
|
|
7701
|
+
}
|
|
7702
|
+
function SessionsListSkeleton() {
|
|
7703
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "payman-v2-sessions-skeleton", children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-skeleton-row", children: [
|
|
7704
|
+
/* @__PURE__ */ jsx(
|
|
7705
|
+
"div",
|
|
7706
|
+
{
|
|
7707
|
+
className: "payman-v2-sessions-skeleton-line payman-v2-sessions-skeleton-line-title",
|
|
7708
|
+
style: { animationDelay: `${i * 90}ms`, width: `${60 + i * 13 % 30}%` }
|
|
7709
|
+
}
|
|
7710
|
+
),
|
|
7711
|
+
/* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-skeleton-meta", children: [
|
|
7712
|
+
/* @__PURE__ */ jsx(
|
|
7713
|
+
"div",
|
|
7714
|
+
{
|
|
7715
|
+
className: "payman-v2-sessions-skeleton-line payman-v2-sessions-skeleton-pill",
|
|
7716
|
+
style: { animationDelay: `${i * 90 + 60}ms` }
|
|
7717
|
+
}
|
|
7718
|
+
),
|
|
7719
|
+
/* @__PURE__ */ jsx(
|
|
7720
|
+
"div",
|
|
7721
|
+
{
|
|
7722
|
+
className: "payman-v2-sessions-skeleton-line payman-v2-sessions-skeleton-pill",
|
|
7723
|
+
style: { animationDelay: `${i * 90 + 120}ms` }
|
|
7724
|
+
}
|
|
7725
|
+
)
|
|
7726
|
+
] })
|
|
7727
|
+
] }, i)) });
|
|
7728
|
+
}
|
|
7729
|
+
function SessionRow({
|
|
7730
|
+
session,
|
|
7731
|
+
isSelected,
|
|
7732
|
+
isMenuOpen,
|
|
7733
|
+
onSelect,
|
|
7734
|
+
onToggleMenu,
|
|
7735
|
+
onCloseMenu,
|
|
7736
|
+
actions
|
|
7737
|
+
}) {
|
|
7738
|
+
const menuRef = useRef(null);
|
|
7739
|
+
const clipRef = useRef(null);
|
|
7740
|
+
const textRef = useRef(null);
|
|
7741
|
+
const [overflowPx, setOverflowPx] = useState(0);
|
|
7742
|
+
const [scrolling, setScrolling] = useState(false);
|
|
7743
|
+
useEffect(() => {
|
|
7744
|
+
if (!isMenuOpen) return;
|
|
7745
|
+
const handlePointerDown = (event) => {
|
|
7746
|
+
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
7747
|
+
onCloseMenu();
|
|
7748
|
+
}
|
|
7749
|
+
};
|
|
7750
|
+
document.addEventListener("mousedown", handlePointerDown);
|
|
7751
|
+
return () => document.removeEventListener("mousedown", handlePointerDown);
|
|
7752
|
+
}, [isMenuOpen, onCloseMenu]);
|
|
7753
|
+
useEffect(() => {
|
|
7754
|
+
const clip = clipRef.current;
|
|
7755
|
+
const text = textRef.current;
|
|
7756
|
+
if (!clip || !text) return;
|
|
7757
|
+
const measure = () => setOverflowPx(Math.max(0, text.scrollWidth - clip.clientWidth));
|
|
7758
|
+
measure();
|
|
7759
|
+
const ro = new ResizeObserver(measure);
|
|
7760
|
+
ro.observe(clip);
|
|
7761
|
+
return () => ro.disconnect();
|
|
7762
|
+
}, [session.title]);
|
|
7763
|
+
const truncated = overflowPx > 2;
|
|
7764
|
+
const messageCount = session.messageCount ?? 0;
|
|
7765
|
+
const title = session.title?.trim() || "New chat";
|
|
7766
|
+
const relativeTime = formatRelativeTime(session.lastMessageAt);
|
|
7767
|
+
return /* @__PURE__ */ jsxs(
|
|
7768
|
+
"div",
|
|
7769
|
+
{
|
|
7770
|
+
className: cn(
|
|
7771
|
+
"payman-v2-session-row",
|
|
7772
|
+
isSelected && "payman-v2-session-row-selected"
|
|
7773
|
+
),
|
|
7774
|
+
children: [
|
|
7775
|
+
/* @__PURE__ */ jsxs(
|
|
7776
|
+
"button",
|
|
7777
|
+
{
|
|
7778
|
+
type: "button",
|
|
7779
|
+
className: "payman-v2-session-row-main",
|
|
7780
|
+
onClick: onSelect,
|
|
7781
|
+
title,
|
|
7782
|
+
onMouseEnter: () => truncated && setScrolling(true),
|
|
7783
|
+
onMouseLeave: () => setScrolling(false),
|
|
7784
|
+
children: [
|
|
7785
|
+
/* @__PURE__ */ jsx(
|
|
7786
|
+
"span",
|
|
7787
|
+
{
|
|
7788
|
+
ref: clipRef,
|
|
7789
|
+
className: "payman-v2-session-row-title",
|
|
7790
|
+
"data-truncated": truncated ? "true" : void 0,
|
|
7791
|
+
"data-scrolling": scrolling ? "true" : void 0,
|
|
7792
|
+
children: /* @__PURE__ */ jsx(
|
|
7793
|
+
"span",
|
|
7794
|
+
{
|
|
7795
|
+
ref: textRef,
|
|
7796
|
+
className: "payman-v2-session-row-title-text",
|
|
7797
|
+
style: scrolling ? {
|
|
7798
|
+
// +16 so the last chars clear the right-edge fade mask.
|
|
7799
|
+
transform: `translateX(-${overflowPx + 16}px)`,
|
|
7800
|
+
// Constant reading pace (~38px/s), so it moves at the same
|
|
7801
|
+
// speed from start to end rather than easing in/out.
|
|
7802
|
+
transitionDuration: `${Math.max(0.9, (overflowPx + 16) / 38)}s`
|
|
7803
|
+
} : void 0,
|
|
7804
|
+
children: title
|
|
7805
|
+
}
|
|
7806
|
+
)
|
|
7807
|
+
}
|
|
7808
|
+
),
|
|
7809
|
+
/* @__PURE__ */ jsxs("span", { className: "payman-v2-session-row-meta", children: [
|
|
7810
|
+
/* @__PURE__ */ jsxs("span", { className: "payman-v2-session-row-meta-item", children: [
|
|
7811
|
+
/* @__PURE__ */ jsx(IconMessage, { size: 12 }),
|
|
7812
|
+
messageCount,
|
|
7813
|
+
" ",
|
|
7814
|
+
messageCount === 1 ? "message" : "messages"
|
|
7815
|
+
] }),
|
|
7816
|
+
relativeTime && /* @__PURE__ */ jsxs("span", { className: "payman-v2-session-row-meta-item", children: [
|
|
7817
|
+
/* @__PURE__ */ jsx(IconClock, { size: 12 }),
|
|
7818
|
+
relativeTime
|
|
7819
|
+
] })
|
|
7820
|
+
] })
|
|
7821
|
+
]
|
|
7822
|
+
}
|
|
7823
|
+
),
|
|
7824
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "payman-v2-session-row-menu-wrap", ref: menuRef, children: [
|
|
7825
|
+
/* @__PURE__ */ jsx(
|
|
7826
|
+
"button",
|
|
7827
|
+
{
|
|
7828
|
+
type: "button",
|
|
7829
|
+
className: cn(
|
|
7830
|
+
"payman-v2-session-row-menu-btn",
|
|
7831
|
+
isMenuOpen && "payman-v2-session-row-menu-btn-active"
|
|
7832
|
+
),
|
|
7833
|
+
onClick: onToggleMenu,
|
|
7834
|
+
"aria-label": "Chat options",
|
|
7835
|
+
"aria-expanded": isMenuOpen,
|
|
7836
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { size: 14 })
|
|
7837
|
+
}
|
|
7838
|
+
),
|
|
7839
|
+
isMenuOpen && /* @__PURE__ */ jsx("div", { className: "payman-v2-session-row-menu", role: "menu", children: actions.map((action) => /* @__PURE__ */ jsx(
|
|
7840
|
+
"button",
|
|
7841
|
+
{
|
|
7842
|
+
type: "button",
|
|
7843
|
+
role: "menuitem",
|
|
7844
|
+
className: cn(
|
|
7845
|
+
"payman-v2-session-row-menu-item",
|
|
7846
|
+
action.destructive && "payman-v2-session-row-menu-item-destructive"
|
|
7847
|
+
),
|
|
7848
|
+
onClick: () => {
|
|
7849
|
+
onCloseMenu();
|
|
7850
|
+
void action.onSelect(session);
|
|
7851
|
+
},
|
|
7852
|
+
children: action.label
|
|
7853
|
+
},
|
|
7854
|
+
action.key
|
|
7855
|
+
)) })
|
|
7856
|
+
] })
|
|
7857
|
+
]
|
|
7858
|
+
}
|
|
7859
|
+
);
|
|
7860
|
+
}
|
|
7861
|
+
var CLOSE_DELAY_MS = 150;
|
|
7862
|
+
var HOVER_OPEN_DELAY_MS = 500;
|
|
7863
|
+
function SessionsPeekPopoverV2({
|
|
7864
|
+
title,
|
|
7865
|
+
newChatLabel,
|
|
7866
|
+
sessions,
|
|
7867
|
+
isLoading,
|
|
7868
|
+
error,
|
|
7869
|
+
onRetry,
|
|
7870
|
+
selectedSessionId,
|
|
7871
|
+
onSelectSession,
|
|
7872
|
+
onNewSession,
|
|
7873
|
+
onExpand,
|
|
7874
|
+
actions
|
|
7875
|
+
}) {
|
|
7876
|
+
const [open, setOpen] = useState(false);
|
|
7877
|
+
const closeTimerRef = useRef(null);
|
|
7878
|
+
const openTimerRef = useRef(null);
|
|
7879
|
+
const cancelClose = useCallback(() => {
|
|
7880
|
+
if (closeTimerRef.current) {
|
|
7881
|
+
clearTimeout(closeTimerRef.current);
|
|
7882
|
+
closeTimerRef.current = null;
|
|
7883
|
+
}
|
|
7884
|
+
}, []);
|
|
7885
|
+
const cancelOpen = useCallback(() => {
|
|
7886
|
+
if (openTimerRef.current) {
|
|
7887
|
+
clearTimeout(openTimerRef.current);
|
|
7888
|
+
openTimerRef.current = null;
|
|
7889
|
+
}
|
|
7890
|
+
}, []);
|
|
7891
|
+
const scheduleClose = useCallback(() => {
|
|
7892
|
+
cancelOpen();
|
|
7893
|
+
cancelClose();
|
|
7894
|
+
closeTimerRef.current = setTimeout(() => setOpen(false), CLOSE_DELAY_MS);
|
|
7895
|
+
}, [cancelOpen, cancelClose]);
|
|
7896
|
+
const handleEnter = useCallback(() => {
|
|
7897
|
+
cancelClose();
|
|
7898
|
+
cancelOpen();
|
|
7899
|
+
openTimerRef.current = setTimeout(() => setOpen(true), HOVER_OPEN_DELAY_MS);
|
|
7900
|
+
}, [cancelClose, cancelOpen]);
|
|
7901
|
+
useEffect(
|
|
7902
|
+
() => () => {
|
|
7903
|
+
cancelOpen();
|
|
7904
|
+
cancelClose();
|
|
7905
|
+
},
|
|
7906
|
+
[cancelOpen, cancelClose]
|
|
7907
|
+
);
|
|
7908
|
+
return /* @__PURE__ */ jsxs(
|
|
7909
|
+
"div",
|
|
7910
|
+
{
|
|
7911
|
+
className: "payman-v2-sessions-peek-anchor",
|
|
7912
|
+
onMouseEnter: handleEnter,
|
|
7913
|
+
onMouseLeave: scheduleClose,
|
|
7914
|
+
children: [
|
|
7915
|
+
/* @__PURE__ */ jsx(
|
|
7916
|
+
"button",
|
|
7917
|
+
{
|
|
7918
|
+
type: "button",
|
|
7919
|
+
className: "payman-v2-sessions-reopen-btn",
|
|
7920
|
+
onClick: onExpand,
|
|
7921
|
+
"aria-label": "Show chats",
|
|
7922
|
+
title: "Show chats",
|
|
7923
|
+
children: /* @__PURE__ */ jsx(PanelLeft, { size: 16 })
|
|
7924
|
+
}
|
|
7925
|
+
),
|
|
7926
|
+
open && /* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-peek", role: "dialog", "aria-label": title, children: [
|
|
7927
|
+
/* @__PURE__ */ jsx("div", { className: "payman-v2-sessions-peek-header", children: /* @__PURE__ */ jsx("span", { className: "payman-v2-sessions-peek-title", children: title }) }),
|
|
7928
|
+
/* @__PURE__ */ jsxs(
|
|
7929
|
+
"button",
|
|
7930
|
+
{
|
|
7931
|
+
type: "button",
|
|
7932
|
+
className: "payman-v2-sessions-new-btn payman-v2-sessions-peek-new-btn",
|
|
7933
|
+
onClick: () => {
|
|
7934
|
+
onNewSession();
|
|
7935
|
+
setOpen(false);
|
|
7936
|
+
},
|
|
7937
|
+
children: [
|
|
7938
|
+
/* @__PURE__ */ jsx(IconNewChat, { size: 14 }),
|
|
7939
|
+
newChatLabel
|
|
7940
|
+
]
|
|
6163
7941
|
}
|
|
6164
|
-
)
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
});
|
|
6169
|
-
return /* @__PURE__ */ jsxs("div", { children: [
|
|
6170
|
-
bars,
|
|
6171
|
-
unaccountedMs > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: 8 }, children: [
|
|
6172
|
-
/* @__PURE__ */ jsxs(
|
|
6173
|
-
"div",
|
|
6174
|
-
{
|
|
6175
|
-
style: {
|
|
6176
|
-
display: "flex",
|
|
6177
|
-
justifyContent: "space-between",
|
|
6178
|
-
fontSize: 12,
|
|
6179
|
-
marginBottom: 4,
|
|
6180
|
-
fontFamily: "ui-monospace, SFMono-Regular, monospace",
|
|
6181
|
-
opacity: 0.7
|
|
6182
|
-
},
|
|
6183
|
-
children: [
|
|
6184
|
-
/* @__PURE__ */ jsx("span", { children: "(unaccounted)" }),
|
|
6185
|
-
/* @__PURE__ */ jsx("span", { children: formatMs(unaccountedMs) })
|
|
6186
|
-
]
|
|
6187
|
-
}
|
|
6188
|
-
),
|
|
6189
|
-
/* @__PURE__ */ jsx(
|
|
6190
|
-
"div",
|
|
6191
|
-
{
|
|
6192
|
-
style: {
|
|
6193
|
-
height: 8,
|
|
6194
|
-
background: "rgba(255,255,255,0.06)",
|
|
6195
|
-
borderRadius: 4,
|
|
6196
|
-
overflow: "hidden"
|
|
6197
|
-
},
|
|
6198
|
-
children: /* @__PURE__ */ jsx(
|
|
6199
|
-
"div",
|
|
7942
|
+
),
|
|
7943
|
+
/* @__PURE__ */ jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
7944
|
+
/* @__PURE__ */ jsx(
|
|
7945
|
+
SessionsListBody,
|
|
6200
7946
|
{
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
7947
|
+
sessions,
|
|
7948
|
+
isLoading,
|
|
7949
|
+
error,
|
|
7950
|
+
onRetry,
|
|
7951
|
+
selectedSessionId,
|
|
7952
|
+
onSelectSession: (sessionId) => {
|
|
7953
|
+
onSelectSession(sessionId);
|
|
7954
|
+
setOpen(false);
|
|
7955
|
+
},
|
|
7956
|
+
actions,
|
|
7957
|
+
compact: true
|
|
6206
7958
|
}
|
|
6207
7959
|
)
|
|
6208
|
-
}
|
|
6209
|
-
|
|
6210
|
-
|
|
7960
|
+
] })
|
|
7961
|
+
]
|
|
7962
|
+
}
|
|
7963
|
+
);
|
|
7964
|
+
}
|
|
7965
|
+
function SessionsBottomSheetV2({
|
|
7966
|
+
title,
|
|
7967
|
+
newChatLabel,
|
|
7968
|
+
sessions,
|
|
7969
|
+
isLoading,
|
|
7970
|
+
error,
|
|
7971
|
+
onRetry,
|
|
7972
|
+
selectedSessionId,
|
|
7973
|
+
onSelectSession,
|
|
7974
|
+
onNewSession,
|
|
7975
|
+
onClose,
|
|
7976
|
+
actions,
|
|
7977
|
+
hasMore,
|
|
7978
|
+
isLoadingMore,
|
|
7979
|
+
onLoadMore
|
|
7980
|
+
}) {
|
|
7981
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7982
|
+
/* @__PURE__ */ jsx(
|
|
7983
|
+
motion.div,
|
|
7984
|
+
{
|
|
7985
|
+
className: "payman-v2-sessions-sheet-backdrop",
|
|
7986
|
+
initial: { opacity: 0 },
|
|
7987
|
+
animate: { opacity: 1 },
|
|
7988
|
+
exit: { opacity: 0 },
|
|
7989
|
+
transition: { duration: 0.2 },
|
|
7990
|
+
onClick: onClose
|
|
7991
|
+
}
|
|
7992
|
+
),
|
|
6211
7993
|
/* @__PURE__ */ jsxs(
|
|
6212
|
-
|
|
7994
|
+
motion.div,
|
|
6213
7995
|
{
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
},
|
|
7996
|
+
className: "payman-v2-sessions-sheet",
|
|
7997
|
+
role: "dialog",
|
|
7998
|
+
"aria-modal": "true",
|
|
7999
|
+
"aria-label": title,
|
|
8000
|
+
initial: { y: "100%" },
|
|
8001
|
+
animate: { y: 0 },
|
|
8002
|
+
exit: { y: "100%" },
|
|
8003
|
+
transition: { type: "spring", damping: 32, stiffness: 320 },
|
|
6223
8004
|
children: [
|
|
6224
|
-
/* @__PURE__ */
|
|
6225
|
-
|
|
6226
|
-
"
|
|
6227
|
-
|
|
8005
|
+
/* @__PURE__ */ jsx("div", { className: "payman-v2-sessions-sheet-grabber", "aria-hidden": true }),
|
|
8006
|
+
/* @__PURE__ */ jsxs("div", { className: "payman-v2-sessions-header", children: [
|
|
8007
|
+
/* @__PURE__ */ jsx("span", { className: "payman-v2-sessions-title", children: title }),
|
|
8008
|
+
/* @__PURE__ */ jsx(
|
|
8009
|
+
"button",
|
|
8010
|
+
{
|
|
8011
|
+
type: "button",
|
|
8012
|
+
className: "payman-v2-sessions-close",
|
|
8013
|
+
onClick: onClose,
|
|
8014
|
+
"aria-label": "Close chats panel",
|
|
8015
|
+
children: /* @__PURE__ */ jsx(X, { size: 16 })
|
|
8016
|
+
}
|
|
8017
|
+
)
|
|
6228
8018
|
] }),
|
|
6229
|
-
/* @__PURE__ */ jsxs("
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
] })
|
|
8019
|
+
/* @__PURE__ */ jsxs("button", { type: "button", className: "payman-v2-sessions-new-btn", onClick: onNewSession, children: [
|
|
8020
|
+
/* @__PURE__ */ jsx(IconNewChat, { size: 16 }),
|
|
8021
|
+
newChatLabel
|
|
8022
|
+
] }),
|
|
8023
|
+
/* @__PURE__ */ jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
8024
|
+
/* @__PURE__ */ jsx(
|
|
8025
|
+
SessionsListBody,
|
|
8026
|
+
{
|
|
8027
|
+
sessions,
|
|
8028
|
+
isLoading,
|
|
8029
|
+
error,
|
|
8030
|
+
onRetry,
|
|
8031
|
+
selectedSessionId,
|
|
8032
|
+
onSelectSession,
|
|
8033
|
+
actions,
|
|
8034
|
+
hasMore,
|
|
8035
|
+
isLoadingMore,
|
|
8036
|
+
onLoadMore
|
|
8037
|
+
}
|
|
8038
|
+
)
|
|
6233
8039
|
]
|
|
6234
8040
|
}
|
|
6235
8041
|
)
|
|
@@ -6329,7 +8135,8 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6329
8135
|
onLoadMoreMessages,
|
|
6330
8136
|
isLoadingMoreMessages = false,
|
|
6331
8137
|
hasMoreMessages = false,
|
|
6332
|
-
chat
|
|
8138
|
+
chat,
|
|
8139
|
+
sessionsPanel
|
|
6333
8140
|
}, ref) {
|
|
6334
8141
|
const [inputValue, setInputValue] = useState("");
|
|
6335
8142
|
const prevInputValueRef = useRef(inputValue);
|
|
@@ -6342,6 +8149,25 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6342
8149
|
const chatInputV2Ref = useRef(null);
|
|
6343
8150
|
const messageListV2Ref = useRef(null);
|
|
6344
8151
|
const resetToEmptyStateRef = useRef(false);
|
|
8152
|
+
const rootRef = useRef(null);
|
|
8153
|
+
const [isCompact, setIsCompact] = useState(false);
|
|
8154
|
+
useEffect(() => {
|
|
8155
|
+
const el = rootRef.current;
|
|
8156
|
+
if (!el) return;
|
|
8157
|
+
const ro = new ResizeObserver((entries) => {
|
|
8158
|
+
const width = entries[0]?.contentRect.width;
|
|
8159
|
+
if (width != null) setIsCompact(width < COMPACT_BREAKPOINT_PX);
|
|
8160
|
+
});
|
|
8161
|
+
ro.observe(el);
|
|
8162
|
+
return () => ro.disconnect();
|
|
8163
|
+
}, []);
|
|
8164
|
+
const wasCompactRef = useRef(isCompact);
|
|
8165
|
+
useEffect(() => {
|
|
8166
|
+
if (isCompact && !wasCompactRef.current && sessionsPanel?.open) {
|
|
8167
|
+
sessionsPanel.onToggle();
|
|
8168
|
+
}
|
|
8169
|
+
wasCompactRef.current = isCompact;
|
|
8170
|
+
}, [isCompact, sessionsPanel]);
|
|
6345
8171
|
useEffect(() => {
|
|
6346
8172
|
if (config.sentryDsn) {
|
|
6347
8173
|
initSentryIfNeeded(config.sentryDsn);
|
|
@@ -6386,6 +8212,15 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6386
8212
|
const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
|
|
6387
8213
|
const dismissNotification = chat.dismissNotification ?? NOOP;
|
|
6388
8214
|
const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
|
|
8215
|
+
const expiredUserActionIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
8216
|
+
const expireUserActionOnce = useCallback(
|
|
8217
|
+
(userActionId) => {
|
|
8218
|
+
if (expiredUserActionIdsRef.current.has(userActionId)) return;
|
|
8219
|
+
expiredUserActionIdsRef.current.add(userActionId);
|
|
8220
|
+
void expireUserAction2(userActionId);
|
|
8221
|
+
},
|
|
8222
|
+
[expireUserAction2]
|
|
8223
|
+
);
|
|
6389
8224
|
const {
|
|
6390
8225
|
transcribedText,
|
|
6391
8226
|
isAvailable: voiceAvailable,
|
|
@@ -6487,13 +8322,20 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6487
8322
|
if (isRecording) {
|
|
6488
8323
|
stopRecording();
|
|
6489
8324
|
}
|
|
6490
|
-
|
|
8325
|
+
if (sessionsPanel?.onNewSession) {
|
|
8326
|
+
sessionsPanel.onNewSession();
|
|
8327
|
+
if (isCompact && sessionsPanel.open) sessionsPanel.onToggle();
|
|
8328
|
+
} else {
|
|
8329
|
+
resetSession();
|
|
8330
|
+
}
|
|
6491
8331
|
onResetSession?.();
|
|
6492
8332
|
}, [
|
|
6493
8333
|
clearTranscript,
|
|
6494
8334
|
isRecording,
|
|
8335
|
+
isCompact,
|
|
6495
8336
|
onResetSession,
|
|
6496
8337
|
resetSession,
|
|
8338
|
+
sessionsPanel,
|
|
6497
8339
|
stopRecording
|
|
6498
8340
|
]);
|
|
6499
8341
|
const requestResetSession = useCallback(() => {
|
|
@@ -6507,8 +8349,9 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6507
8349
|
clearMessages,
|
|
6508
8350
|
cancelStream,
|
|
6509
8351
|
getSessionId,
|
|
6510
|
-
getMessages
|
|
6511
|
-
|
|
8352
|
+
getMessages,
|
|
8353
|
+
refreshSessions: sessionsPanel?.refetch ?? NOOP
|
|
8354
|
+
}), [performResetSession, clearMessages, cancelStream, getSessionId, getMessages, sessionsPanel?.refetch]);
|
|
6512
8355
|
const {
|
|
6513
8356
|
placeholder = "Type your message...",
|
|
6514
8357
|
emptyStateText = "What can I help with?",
|
|
@@ -6628,6 +8471,13 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6628
8471
|
};
|
|
6629
8472
|
const userActionPrompts = isUserActionSupported ? userActionState.prompts : void 0;
|
|
6630
8473
|
const notifications = userActionState.notifications;
|
|
8474
|
+
const dockableUserActionPrompts = userActionPrompts?.filter(
|
|
8475
|
+
(prompt) => prompt.kind !== "notification" && (prompt.status === "pending" || prompt.status === "submitting" || prompt.status === "stale")
|
|
8476
|
+
);
|
|
8477
|
+
const dockedPendingPrompts = dockableUserActionPrompts?.filter(
|
|
8478
|
+
(prompt) => prompt.status === "pending"
|
|
8479
|
+
);
|
|
8480
|
+
const dockedPrompt = dockedPendingPrompts?.[dockedPendingPrompts.length - 1] ?? dockableUserActionPrompts?.[dockableUserActionPrompts.length - 1];
|
|
6631
8481
|
const handleV2Send = (text) => {
|
|
6632
8482
|
if (isRecording) stopRecording();
|
|
6633
8483
|
if (text.trim() && !disableInput && isSessionParamsConfigured) {
|
|
@@ -6676,160 +8526,236 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6676
8526
|
return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
|
|
6677
8527
|
"div",
|
|
6678
8528
|
{
|
|
8529
|
+
ref: rootRef,
|
|
6679
8530
|
className: cn("payman-v2-root", className),
|
|
6680
8531
|
style,
|
|
6681
8532
|
children: [
|
|
6682
8533
|
children,
|
|
6683
|
-
/* @__PURE__ */
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
8534
|
+
/* @__PURE__ */ jsxs("div", { className: "payman-v2-body", children: [
|
|
8535
|
+
sessionsPanel && !isCompact && /* @__PURE__ */ jsx(
|
|
8536
|
+
SessionsSidebarV2,
|
|
8537
|
+
{
|
|
8538
|
+
open: sessionsPanel.open,
|
|
8539
|
+
onClose: sessionsPanel.onToggle,
|
|
8540
|
+
title: sessionsPanel.title,
|
|
8541
|
+
newChatLabel: sessionsPanel.newChatLabel,
|
|
8542
|
+
sessions: sessionsPanel.sessionsList,
|
|
8543
|
+
isLoading: sessionsPanel.isLoadingList,
|
|
8544
|
+
error: sessionsPanel.listError,
|
|
8545
|
+
onRetry: sessionsPanel.refetch,
|
|
8546
|
+
selectedSessionId: sessionsPanel.activeSessionId,
|
|
8547
|
+
onSelectSession: sessionsPanel.onSelectSession,
|
|
8548
|
+
onNewSession: requestResetSession,
|
|
8549
|
+
actions: sessionsPanel.actions,
|
|
8550
|
+
hasMore: sessionsPanel.hasMore,
|
|
8551
|
+
isLoadingMore: sessionsPanel.isLoadingMore,
|
|
8552
|
+
onLoadMore: sessionsPanel.onLoadMore
|
|
8553
|
+
}
|
|
8554
|
+
),
|
|
8555
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: sessionsPanel && isCompact && sessionsPanel.open && /* @__PURE__ */ jsx(
|
|
8556
|
+
SessionsBottomSheetV2,
|
|
8557
|
+
{
|
|
8558
|
+
title: sessionsPanel.title,
|
|
8559
|
+
newChatLabel: sessionsPanel.newChatLabel,
|
|
8560
|
+
sessions: sessionsPanel.sessionsList,
|
|
8561
|
+
isLoading: sessionsPanel.isLoadingList,
|
|
8562
|
+
error: sessionsPanel.listError,
|
|
8563
|
+
onRetry: sessionsPanel.refetch,
|
|
8564
|
+
selectedSessionId: sessionsPanel.activeSessionId,
|
|
8565
|
+
onSelectSession: (sessionId) => {
|
|
8566
|
+
sessionsPanel.onSelectSession(sessionId);
|
|
8567
|
+
sessionsPanel.onToggle();
|
|
8568
|
+
},
|
|
8569
|
+
onNewSession: requestResetSession,
|
|
8570
|
+
onClose: sessionsPanel.onToggle,
|
|
8571
|
+
actions: sessionsPanel.actions,
|
|
8572
|
+
hasMore: sessionsPanel.hasMore,
|
|
8573
|
+
isLoadingMore: sessionsPanel.isLoadingMore,
|
|
8574
|
+
onLoadMore: sessionsPanel.onLoadMore
|
|
8575
|
+
},
|
|
8576
|
+
"sessions-bottom-sheet"
|
|
8577
|
+
) }),
|
|
8578
|
+
/* @__PURE__ */ jsxs("div", { className: "payman-v2-chat-column", children: [
|
|
8579
|
+
sessionsPanel?.isLoadingMessages && /* @__PURE__ */ jsx("div", { className: "payman-v2-messages-loading-overlay", children: /* @__PURE__ */ jsx("span", { className: "payman-v2-spinner" }) }),
|
|
8580
|
+
sessionsPanel && !sessionsPanel.open && /* @__PURE__ */ jsx(
|
|
8581
|
+
SessionsPeekPopoverV2,
|
|
8582
|
+
{
|
|
8583
|
+
title: sessionsPanel.title,
|
|
8584
|
+
newChatLabel: sessionsPanel.newChatLabel,
|
|
8585
|
+
sessions: sessionsPanel.sessionsList,
|
|
8586
|
+
isLoading: sessionsPanel.isLoadingList,
|
|
8587
|
+
error: sessionsPanel.listError,
|
|
8588
|
+
onRetry: sessionsPanel.refetch,
|
|
8589
|
+
selectedSessionId: sessionsPanel.activeSessionId,
|
|
8590
|
+
onSelectSession: sessionsPanel.onSelectSession,
|
|
8591
|
+
onNewSession: requestResetSession,
|
|
8592
|
+
onExpand: sessionsPanel.onToggle,
|
|
8593
|
+
actions: sessionsPanel.actions
|
|
8594
|
+
}
|
|
8595
|
+
),
|
|
8596
|
+
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? /* @__PURE__ */ jsx(
|
|
8597
|
+
motion.div,
|
|
8598
|
+
{
|
|
8599
|
+
initial: { opacity: 1 },
|
|
8600
|
+
exit: { opacity: 0 },
|
|
8601
|
+
transition: { duration: 0.3 },
|
|
8602
|
+
className: "payman-v2-chat-layout",
|
|
8603
|
+
style: { justifyContent: "center", alignItems: "center" },
|
|
8604
|
+
children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1, width: "100%" }, children: [
|
|
8605
|
+
/* @__PURE__ */ jsx(
|
|
8606
|
+
MessageList,
|
|
8607
|
+
{
|
|
8608
|
+
messages,
|
|
8609
|
+
isLoading: false,
|
|
8610
|
+
emptyStateText,
|
|
8611
|
+
showEmptyStateIcon,
|
|
8612
|
+
emptyStateComponent,
|
|
8613
|
+
layout,
|
|
8614
|
+
showTimestamps,
|
|
8615
|
+
stage: config.stage || "DEVELOPMENT",
|
|
8616
|
+
animated,
|
|
8617
|
+
showAgentName,
|
|
8618
|
+
agentName,
|
|
8619
|
+
showAvatars,
|
|
8620
|
+
showUserAvatar,
|
|
8621
|
+
showAssistantAvatar,
|
|
8622
|
+
showExecutionSteps,
|
|
8623
|
+
showStreamingDot,
|
|
8624
|
+
streamingStepsText,
|
|
8625
|
+
completedStepsText,
|
|
8626
|
+
onExecutionTraceClick,
|
|
8627
|
+
onLoadMoreMessages,
|
|
8628
|
+
isLoadingMoreMessages,
|
|
8629
|
+
hasMoreMessages
|
|
8630
|
+
}
|
|
8631
|
+
),
|
|
8632
|
+
/* @__PURE__ */ jsx(
|
|
8633
|
+
motion.div,
|
|
8634
|
+
{
|
|
8635
|
+
initial: { opacity: 0 },
|
|
8636
|
+
animate: { opacity: 1 },
|
|
8637
|
+
transition: { duration: 0.18 },
|
|
8638
|
+
style: { width: "100%" },
|
|
8639
|
+
children: hasAskPermission && /* @__PURE__ */ jsx(
|
|
8640
|
+
ChatInputV2,
|
|
8641
|
+
{
|
|
8642
|
+
ref: chatInputV2Ref,
|
|
8643
|
+
onSend: handleV2Send,
|
|
8644
|
+
onCancel: cancelStream,
|
|
8645
|
+
disabled: isV2InputDisabled,
|
|
8646
|
+
isStreaming: isWaitingForResponse,
|
|
8647
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
8648
|
+
enableVoice: config.enableVoice === true,
|
|
8649
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
8650
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
8651
|
+
isRecording,
|
|
8652
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
8653
|
+
onCancelRecording: handleCancelRecording,
|
|
8654
|
+
onConfirmRecording: handleConfirmRecording,
|
|
8655
|
+
showResetSession,
|
|
8656
|
+
onResetSession: requestResetSession,
|
|
8657
|
+
showAttachmentButton,
|
|
8658
|
+
showUploadImageButton,
|
|
8659
|
+
showAttachFileButton,
|
|
8660
|
+
onUploadImageClick,
|
|
8661
|
+
onAttachFileClick,
|
|
8662
|
+
editingMessageId,
|
|
8663
|
+
onClearEditing: handleClearEditing,
|
|
8664
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
8665
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
8666
|
+
slashCommands
|
|
8667
|
+
}
|
|
8668
|
+
)
|
|
8669
|
+
}
|
|
8670
|
+
)
|
|
8671
|
+
] })
|
|
8672
|
+
},
|
|
8673
|
+
"v2-empty"
|
|
8674
|
+
) : /* @__PURE__ */ jsxs(
|
|
8675
|
+
motion.div,
|
|
8676
|
+
{
|
|
8677
|
+
initial: { opacity: 0 },
|
|
8678
|
+
animate: { opacity: 1 },
|
|
8679
|
+
transition: { duration: 0.25 },
|
|
8680
|
+
className: "payman-v2-chat-layout",
|
|
8681
|
+
children: [
|
|
8682
|
+
/* @__PURE__ */ jsx(
|
|
8683
|
+
MessageListV2,
|
|
8684
|
+
{
|
|
8685
|
+
ref: messageListV2Ref,
|
|
8686
|
+
messages,
|
|
8687
|
+
isStreaming: isWaitingForResponse,
|
|
8688
|
+
onEditUserMessage: handleEditMessageDraft,
|
|
8689
|
+
onRetryUserMessage: handleRetryUserMessage,
|
|
8690
|
+
onImageClick: handleImageClick,
|
|
8691
|
+
onExecutionTraceClick,
|
|
8692
|
+
messageActions,
|
|
8693
|
+
retryDisabled: isWaitingForResponse,
|
|
8694
|
+
typingSpeed: config.typingSpeed ?? 4,
|
|
8695
|
+
userActionPrompts,
|
|
8696
|
+
dockedUserActionId: dockedPrompt?.userActionId,
|
|
8697
|
+
notifications,
|
|
8698
|
+
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
8699
|
+
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
8700
|
+
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
8701
|
+
onExpireUserAction: isUserActionSupported ? async (id) => expireUserActionOnce(id) : void 0,
|
|
8702
|
+
onDismissNotification: dismissNotification,
|
|
8703
|
+
onSubmitFeedback: handleSubmitFeedback
|
|
8704
|
+
}
|
|
8705
|
+
),
|
|
8706
|
+
/* @__PURE__ */ jsx(
|
|
8707
|
+
StreamingIndicatorV2,
|
|
6728
8708
|
{
|
|
6729
|
-
ref: chatInputV2Ref,
|
|
6730
|
-
onSend: handleV2Send,
|
|
6731
|
-
onCancel: cancelStream,
|
|
6732
|
-
disabled: isV2InputDisabled,
|
|
6733
8709
|
isStreaming: isWaitingForResponse,
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
8710
|
+
loadingAnimation: config.loadingAnimation
|
|
8711
|
+
}
|
|
8712
|
+
),
|
|
8713
|
+
hasAskPermission && /* @__PURE__ */ jsx(
|
|
8714
|
+
UserActionDock,
|
|
8715
|
+
{
|
|
8716
|
+
prompt: isUserActionSupported ? dockedPrompt : void 0,
|
|
8717
|
+
onSubmit: submitUserAction2,
|
|
8718
|
+
onCancel: cancelUserAction2,
|
|
8719
|
+
onResend: resendUserAction2,
|
|
8720
|
+
onExpired: expireUserActionOnce,
|
|
8721
|
+
children: /* @__PURE__ */ jsx(
|
|
8722
|
+
ChatInputV2,
|
|
8723
|
+
{
|
|
8724
|
+
ref: chatInputV2Ref,
|
|
8725
|
+
onSend: handleV2Send,
|
|
8726
|
+
onCancel: cancelStream,
|
|
8727
|
+
disabled: isV2InputDisabled,
|
|
8728
|
+
isStreaming: isWaitingForResponse,
|
|
8729
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
8730
|
+
enableVoice: config.enableVoice === true,
|
|
8731
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
8732
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
8733
|
+
isRecording,
|
|
8734
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
8735
|
+
onCancelRecording: handleCancelRecording,
|
|
8736
|
+
onConfirmRecording: handleConfirmRecording,
|
|
8737
|
+
showResetSession,
|
|
8738
|
+
onResetSession: requestResetSession,
|
|
8739
|
+
showAttachmentButton,
|
|
8740
|
+
showUploadImageButton,
|
|
8741
|
+
showAttachFileButton,
|
|
8742
|
+
onUploadImageClick,
|
|
8743
|
+
onAttachFileClick,
|
|
8744
|
+
editingMessageId,
|
|
8745
|
+
onClearEditing: handleClearEditing,
|
|
8746
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
8747
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
8748
|
+
slashCommands
|
|
8749
|
+
}
|
|
8750
|
+
)
|
|
6754
8751
|
}
|
|
6755
8752
|
)
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
)
|
|
6762
|
-
motion.div,
|
|
6763
|
-
{
|
|
6764
|
-
initial: hasEverSentMessage ? { opacity: 0 } : false,
|
|
6765
|
-
animate: { opacity: 1 },
|
|
6766
|
-
transition: { duration: 0.3 },
|
|
6767
|
-
className: "payman-v2-chat-layout",
|
|
6768
|
-
children: [
|
|
6769
|
-
/* @__PURE__ */ jsx(
|
|
6770
|
-
MessageListV2,
|
|
6771
|
-
{
|
|
6772
|
-
ref: messageListV2Ref,
|
|
6773
|
-
messages,
|
|
6774
|
-
isStreaming: isWaitingForResponse,
|
|
6775
|
-
onEditUserMessage: handleEditMessageDraft,
|
|
6776
|
-
onRetryUserMessage: handleRetryUserMessage,
|
|
6777
|
-
onImageClick: handleImageClick,
|
|
6778
|
-
onExecutionTraceClick,
|
|
6779
|
-
messageActions,
|
|
6780
|
-
retryDisabled: isWaitingForResponse,
|
|
6781
|
-
typingSpeed: config.typingSpeed ?? 4,
|
|
6782
|
-
userActionPrompts,
|
|
6783
|
-
notifications,
|
|
6784
|
-
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
6785
|
-
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
6786
|
-
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
6787
|
-
onExpireUserAction: isUserActionSupported ? expireUserAction2 : void 0,
|
|
6788
|
-
onDismissNotification: dismissNotification,
|
|
6789
|
-
onSubmitFeedback: handleSubmitFeedback
|
|
6790
|
-
}
|
|
6791
|
-
),
|
|
6792
|
-
/* @__PURE__ */ jsx(
|
|
6793
|
-
StreamingIndicatorV2,
|
|
6794
|
-
{
|
|
6795
|
-
isStreaming: isWaitingForResponse,
|
|
6796
|
-
loadingAnimation: config.loadingAnimation
|
|
6797
|
-
}
|
|
6798
|
-
),
|
|
6799
|
-
hasAskPermission && /* @__PURE__ */ jsx(
|
|
6800
|
-
ChatInputV2,
|
|
6801
|
-
{
|
|
6802
|
-
ref: chatInputV2Ref,
|
|
6803
|
-
onSend: handleV2Send,
|
|
6804
|
-
onCancel: cancelStream,
|
|
6805
|
-
disabled: isV2InputDisabled,
|
|
6806
|
-
isStreaming: isWaitingForResponse,
|
|
6807
|
-
placeholder: isRecording ? "Listening..." : placeholder,
|
|
6808
|
-
enableVoice: config.enableVoice === true,
|
|
6809
|
-
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
6810
|
-
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
6811
|
-
isRecording,
|
|
6812
|
-
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
6813
|
-
onCancelRecording: handleCancelRecording,
|
|
6814
|
-
onConfirmRecording: handleConfirmRecording,
|
|
6815
|
-
showResetSession,
|
|
6816
|
-
onResetSession: requestResetSession,
|
|
6817
|
-
showAttachmentButton,
|
|
6818
|
-
showUploadImageButton,
|
|
6819
|
-
showAttachFileButton,
|
|
6820
|
-
onUploadImageClick,
|
|
6821
|
-
onAttachFileClick,
|
|
6822
|
-
editingMessageId,
|
|
6823
|
-
onClearEditing: handleClearEditing,
|
|
6824
|
-
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
6825
|
-
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
6826
|
-
slashCommands
|
|
6827
|
-
}
|
|
6828
|
-
)
|
|
6829
|
-
]
|
|
6830
|
-
},
|
|
6831
|
-
"v2-chat"
|
|
6832
|
-
) }),
|
|
8753
|
+
]
|
|
8754
|
+
},
|
|
8755
|
+
"v2-chat"
|
|
8756
|
+
) })
|
|
8757
|
+
] })
|
|
8758
|
+
] }),
|
|
6833
8759
|
/* @__PURE__ */ jsx(
|
|
6834
8760
|
ImageLightboxV2,
|
|
6835
8761
|
{
|
|
@@ -6860,14 +8786,163 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
|
|
|
6860
8786
|
}
|
|
6861
8787
|
) });
|
|
6862
8788
|
});
|
|
6863
|
-
var
|
|
6864
|
-
function
|
|
8789
|
+
var PaymanChatWithChat = forwardRef(
|
|
8790
|
+
function PaymanChatWithChat2(props, ref) {
|
|
6865
8791
|
const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
|
|
6866
8792
|
const chat = useChatV2(props.config, mergedCallbacks);
|
|
6867
8793
|
return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
|
|
6868
8794
|
}
|
|
6869
8795
|
);
|
|
8796
|
+
function AvailabilityNotice({ message }) {
|
|
8797
|
+
return /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center p-4", children: /* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx("div", { className: "text-muted-foreground text-sm", children: message }) }) });
|
|
8798
|
+
}
|
|
8799
|
+
var DEFAULT_AGENT_DISABLED_MESSAGE = "Chat is currently unavailable. Please try again later.";
|
|
8800
|
+
var DEFAULT_USER_BLOCKED_MESSAGE = "Chat isn't available for your account right now.";
|
|
8801
|
+
var COMPACT_BREAKPOINT_PX = 640;
|
|
8802
|
+
var PaymanChat = forwardRef(
|
|
8803
|
+
function PaymanChat2(props, ref) {
|
|
8804
|
+
const { config } = props;
|
|
8805
|
+
const sessionsConfig = config.sessions;
|
|
8806
|
+
const availabilityData = useAgentConfig({
|
|
8807
|
+
api: config.api,
|
|
8808
|
+
availability: config.availability
|
|
8809
|
+
});
|
|
8810
|
+
const agentUnavailable = availabilityData.enabled && availabilityData.available === false;
|
|
8811
|
+
const availabilityStatus = availabilityData.status;
|
|
8812
|
+
const availabilityGateOpen = !availabilityData.enabled || availabilityData.available === true || availabilityData.available === null && !availabilityData.isLoading;
|
|
8813
|
+
const gatedSessionsConfig = useMemo(
|
|
8814
|
+
() => sessionsConfig ? {
|
|
8815
|
+
...sessionsConfig,
|
|
8816
|
+
enabled: sessionsConfig.enabled === true && availabilityGateOpen
|
|
8817
|
+
} : sessionsConfig,
|
|
8818
|
+
[sessionsConfig, availabilityGateOpen]
|
|
8819
|
+
);
|
|
8820
|
+
const sessionsData = useChatSessions({
|
|
8821
|
+
api: config.api,
|
|
8822
|
+
sessions: gatedSessionsConfig,
|
|
8823
|
+
initialSessionId: config.initialSessionId
|
|
8824
|
+
});
|
|
8825
|
+
const [sidebarOpen, setSidebarOpen] = useState(
|
|
8826
|
+
sessionsConfig?.defaultOpen !== false
|
|
8827
|
+
);
|
|
8828
|
+
const toggleSidebar = useCallback(() => setSidebarOpen((open) => !open), []);
|
|
8829
|
+
const effectiveConfig = useMemo(() => {
|
|
8830
|
+
if (!sessionsData.enabled) return config;
|
|
8831
|
+
return {
|
|
8832
|
+
...config,
|
|
8833
|
+
initialSessionId: sessionsData.activeSessionId,
|
|
8834
|
+
initialMessages: sessionsData.selectedMessages,
|
|
8835
|
+
autoGenerateSessionId: false,
|
|
8836
|
+
// Scope the message store per active session. The base userId alone
|
|
8837
|
+
// is shared across every session, so its chatStore entry would leak
|
|
8838
|
+
// the previous chat's messages into a newly-selected or brand-new
|
|
8839
|
+
// session (getStoredOrInitialMessages prefers the store over
|
|
8840
|
+
// initialMessages). Per-session keys give each chat a clean slate.
|
|
8841
|
+
userId: config.userId ? `${config.userId}::${sessionsData.activeSessionId}` : void 0
|
|
8842
|
+
};
|
|
8843
|
+
}, [
|
|
8844
|
+
config,
|
|
8845
|
+
sessionsData.enabled,
|
|
8846
|
+
sessionsData.activeSessionId,
|
|
8847
|
+
sessionsData.selectedMessages
|
|
8848
|
+
]);
|
|
8849
|
+
const sessionsPanel = useMemo(() => {
|
|
8850
|
+
if (!sessionsData.enabled) return void 0;
|
|
8851
|
+
return {
|
|
8852
|
+
open: sidebarOpen,
|
|
8853
|
+
onToggle: toggleSidebar,
|
|
8854
|
+
title: sessionsConfig?.title ?? "Chats",
|
|
8855
|
+
newChatLabel: sessionsConfig?.newChatLabel ?? "Start New Chat",
|
|
8856
|
+
sessionsList: sessionsData.sessionsList,
|
|
8857
|
+
isLoadingList: sessionsData.isLoadingList,
|
|
8858
|
+
listError: sessionsData.listError,
|
|
8859
|
+
activeSessionId: sessionsData.activeSessionId,
|
|
8860
|
+
onSelectSession: sessionsData.selectSession,
|
|
8861
|
+
onNewSession: sessionsData.startNewSession,
|
|
8862
|
+
actions: sessionsConfig?.actions,
|
|
8863
|
+
refetch: sessionsData.refetch,
|
|
8864
|
+
hasMore: sessionsData.hasMore,
|
|
8865
|
+
isLoadingMore: sessionsData.isLoadingMore,
|
|
8866
|
+
onLoadMore: sessionsData.loadMore,
|
|
8867
|
+
isLoadingMessages: sessionsData.isLoadingMessages
|
|
8868
|
+
};
|
|
8869
|
+
}, [
|
|
8870
|
+
sessionsData.enabled,
|
|
8871
|
+
sessionsData.sessionsList,
|
|
8872
|
+
sessionsData.isLoadingList,
|
|
8873
|
+
sessionsData.listError,
|
|
8874
|
+
sessionsData.activeSessionId,
|
|
8875
|
+
sessionsData.selectSession,
|
|
8876
|
+
sessionsData.startNewSession,
|
|
8877
|
+
sessionsData.refetch,
|
|
8878
|
+
sessionsData.hasMore,
|
|
8879
|
+
sessionsData.isLoadingMore,
|
|
8880
|
+
sessionsData.loadMore,
|
|
8881
|
+
sessionsData.isLoadingMessages,
|
|
8882
|
+
sidebarOpen,
|
|
8883
|
+
toggleSidebar,
|
|
8884
|
+
sessionsConfig?.title,
|
|
8885
|
+
sessionsConfig?.newChatLabel,
|
|
8886
|
+
sessionsConfig?.actions
|
|
8887
|
+
]);
|
|
8888
|
+
const callbacksWithSessionsRefresh = useMemo(() => {
|
|
8889
|
+
if (!sessionsData.enabled) return props.callbacks;
|
|
8890
|
+
return {
|
|
8891
|
+
...props.callbacks,
|
|
8892
|
+
// Reflect the message in the sidebar the instant it's sent, before
|
|
8893
|
+
// the server round-trip — the refetch below reconciles on complete.
|
|
8894
|
+
onMessageSent: (message) => {
|
|
8895
|
+
props.callbacks?.onMessageSent?.(message);
|
|
8896
|
+
sessionsData.noteSentMessage(message);
|
|
8897
|
+
},
|
|
8898
|
+
onStreamComplete: (message) => {
|
|
8899
|
+
props.callbacks?.onStreamComplete?.(message);
|
|
8900
|
+
sessionsData.refetch();
|
|
8901
|
+
}
|
|
8902
|
+
};
|
|
8903
|
+
}, [sessionsData.enabled, props.callbacks, sessionsData.refetch, sessionsData.noteSentMessage]);
|
|
8904
|
+
const availabilityPending = availabilityData.enabled && availabilityData.isLoading && availabilityData.available === null;
|
|
8905
|
+
if (availabilityPending) {
|
|
8906
|
+
return /* @__PURE__ */ jsxs(
|
|
8907
|
+
"div",
|
|
8908
|
+
{
|
|
8909
|
+
className: cn("bg-background overflow-hidden flex flex-col flex-[4]", props.className),
|
|
8910
|
+
style: props.style,
|
|
8911
|
+
children: [
|
|
8912
|
+
props.children,
|
|
8913
|
+
/* @__PURE__ */ jsx("div", { className: "payman-v2-chat-loading", children: /* @__PURE__ */ jsx("span", { className: "payman-v2-spinner" }) })
|
|
8914
|
+
]
|
|
8915
|
+
}
|
|
8916
|
+
);
|
|
8917
|
+
}
|
|
8918
|
+
if (agentUnavailable) {
|
|
8919
|
+
const disabledBody = availabilityStatus === "blocked" ? config.availability?.blockedComponent ?? /* @__PURE__ */ jsx(AvailabilityNotice, { message: DEFAULT_USER_BLOCKED_MESSAGE }) : config.availability?.disabledComponent ?? /* @__PURE__ */ jsx(AvailabilityNotice, { message: DEFAULT_AGENT_DISABLED_MESSAGE });
|
|
8920
|
+
return /* @__PURE__ */ jsxs(
|
|
8921
|
+
"div",
|
|
8922
|
+
{
|
|
8923
|
+
className: cn("bg-background overflow-hidden flex flex-col flex-[4]", props.className),
|
|
8924
|
+
style: props.style,
|
|
8925
|
+
children: [
|
|
8926
|
+
props.children,
|
|
8927
|
+
disabledBody
|
|
8928
|
+
]
|
|
8929
|
+
}
|
|
8930
|
+
);
|
|
8931
|
+
}
|
|
8932
|
+
return /* @__PURE__ */ jsx(
|
|
8933
|
+
PaymanChatWithChat,
|
|
8934
|
+
{
|
|
8935
|
+
...props,
|
|
8936
|
+
config: effectiveConfig,
|
|
8937
|
+
callbacks: callbacksWithSessionsRefresh,
|
|
8938
|
+
sessionsPanel,
|
|
8939
|
+
ref
|
|
8940
|
+
},
|
|
8941
|
+
sessionsData.enabled ? sessionsData.activeSessionId : void 0
|
|
8942
|
+
);
|
|
8943
|
+
}
|
|
8944
|
+
);
|
|
6870
8945
|
|
|
6871
|
-
export { PaymanChat, PaymanChatContext, UserActionStaleError, cancelUserAction, captureSentryError, cn, formatDate, resendUserAction, submitUserAction, useChatV2, usePaymanChat, useVoice };
|
|
8946
|
+
export { PaymanChat, PaymanChatContext, UserActionStaleError, cancelUserAction, captureSentryError, cn, formatDate, resendUserAction, submitUserAction, useAgentConfig, useChatV2, usePaymanChat, useVoice };
|
|
6872
8947
|
//# sourceMappingURL=index.mjs.map
|
|
6873
8948
|
//# sourceMappingURL=index.mjs.map
|