@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.js
CHANGED
|
@@ -1155,6 +1155,9 @@ function getUserActionSecondsLeft(prompt) {
|
|
|
1155
1155
|
return void 0;
|
|
1156
1156
|
}
|
|
1157
1157
|
var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
|
|
1158
|
+
function promptSlotKey(p) {
|
|
1159
|
+
return p.toolCallId || p.userActionId;
|
|
1160
|
+
}
|
|
1158
1161
|
function upsertPrompt(prompts, req) {
|
|
1159
1162
|
const idx = prompts.findIndex(
|
|
1160
1163
|
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
@@ -1201,6 +1204,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1201
1204
|
configRef.current = config;
|
|
1202
1205
|
const messagesRef = React.useRef(messages);
|
|
1203
1206
|
messagesRef.current = messages;
|
|
1207
|
+
const pendingSubmissionsRef = React.useRef(/* @__PURE__ */ new Map());
|
|
1204
1208
|
const storeAwareSetMessages = React.useCallback(
|
|
1205
1209
|
(updater) => {
|
|
1206
1210
|
const streamUserId = streamUserIdRef.current;
|
|
@@ -1235,6 +1239,8 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1235
1239
|
if (!config.userId) return EMPTY_USER_ACTION_STATE2;
|
|
1236
1240
|
return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
|
|
1237
1241
|
});
|
|
1242
|
+
const userActionStateRef = React.useRef(userActionState);
|
|
1243
|
+
userActionStateRef.current = userActionState;
|
|
1238
1244
|
const storeAwareSetUserActionState = React.useCallback(
|
|
1239
1245
|
(updater) => {
|
|
1240
1246
|
const streamUserId = streamUserIdRef.current;
|
|
@@ -1262,6 +1268,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1262
1268
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1263
1269
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1264
1270
|
onUserActionRequired: (request) => {
|
|
1271
|
+
const requestSlotKey = promptSlotKey(request);
|
|
1272
|
+
for (const [pendingId, slotKey] of pendingSubmissionsRef.current) {
|
|
1273
|
+
if (slotKey === requestSlotKey) {
|
|
1274
|
+
pendingSubmissionsRef.current.delete(pendingId);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1265
1277
|
storeAwareSetUserActionState((prev) => ({
|
|
1266
1278
|
...prev,
|
|
1267
1279
|
prompts: upsertPrompt(prev.prompts, request)
|
|
@@ -1273,6 +1285,28 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1273
1285
|
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1274
1286
|
);
|
|
1275
1287
|
callbacksRef.current.onUserNotification?.(notification);
|
|
1288
|
+
},
|
|
1289
|
+
// A submitted-but-unconfirmed prompt (see `submitUserAction`) is only
|
|
1290
|
+
// safe to drop once the stream has demonstrably moved on. `onEvent`
|
|
1291
|
+
// in useStreamManagerV2 calls `onStepsUpdate` for *every* processed
|
|
1292
|
+
// stream event, unconditionally — so the first time this fires
|
|
1293
|
+
// after a submission, the event in hand is either the rejection
|
|
1294
|
+
// retry (a fresh `USER_ACTION_REQUIRED`, which the handler above
|
|
1295
|
+
// already deleted this pending entry for, earlier in the very same
|
|
1296
|
+
// event) or genuine forward progress (RUN_IN_PROGRESS, a tool call,
|
|
1297
|
+
// content deltas, RUN_COMPLETED, ...). Anything still pending by
|
|
1298
|
+
// the time we get here therefore means the run resumed normally —
|
|
1299
|
+
// clear it.
|
|
1300
|
+
onStepsUpdate: (steps) => {
|
|
1301
|
+
if (pendingSubmissionsRef.current.size > 0) {
|
|
1302
|
+
const resolved = [...pendingSubmissionsRef.current.keys()];
|
|
1303
|
+
pendingSubmissionsRef.current.clear();
|
|
1304
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1305
|
+
...prev,
|
|
1306
|
+
prompts: prev.prompts.filter((p) => !resolved.includes(p.userActionId))
|
|
1307
|
+
}));
|
|
1308
|
+
}
|
|
1309
|
+
callbacksRef.current.onStepsUpdate?.(steps);
|
|
1276
1310
|
}
|
|
1277
1311
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1278
1312
|
}), []);
|
|
@@ -1408,6 +1442,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1408
1442
|
[storeAwareSetUserActionState]
|
|
1409
1443
|
);
|
|
1410
1444
|
const removePrompt = React.useCallback((userActionId) => {
|
|
1445
|
+
pendingSubmissionsRef.current.delete(userActionId);
|
|
1411
1446
|
storeAwareSetUserActionState((prev) => ({
|
|
1412
1447
|
...prev,
|
|
1413
1448
|
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
@@ -1418,7 +1453,10 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1418
1453
|
setPromptStatus(userActionId, "submitting");
|
|
1419
1454
|
try {
|
|
1420
1455
|
await submitUserAction(configRef.current, userActionId, content);
|
|
1421
|
-
|
|
1456
|
+
const prompt = userActionStateRef.current.prompts.find(
|
|
1457
|
+
(p) => p.userActionId === userActionId
|
|
1458
|
+
);
|
|
1459
|
+
pendingSubmissionsRef.current.set(userActionId, prompt ? promptSlotKey(prompt) : userActionId);
|
|
1422
1460
|
} catch (error) {
|
|
1423
1461
|
if (error instanceof UserActionStaleError) {
|
|
1424
1462
|
setPromptStatus(userActionId, "stale");
|
|
@@ -1429,7 +1467,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1429
1467
|
throw error;
|
|
1430
1468
|
}
|
|
1431
1469
|
},
|
|
1432
|
-
[
|
|
1470
|
+
[setPromptStatus]
|
|
1433
1471
|
);
|
|
1434
1472
|
const cancelUserAction2 = React.useCallback(
|
|
1435
1473
|
async (userActionId) => {
|
|
@@ -1783,6 +1821,284 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1783
1821
|
reset
|
|
1784
1822
|
};
|
|
1785
1823
|
}
|
|
1824
|
+
var DEFAULT_PAGE_SIZE = 20;
|
|
1825
|
+
var DEFAULT_MESSAGES_PAGE_SIZE = 100;
|
|
1826
|
+
function defaultParseSessions(json) {
|
|
1827
|
+
const body = json;
|
|
1828
|
+
const rows = Array.isArray(body?.data) ? body.data : [];
|
|
1829
|
+
const data = rows.map((row) => ({ ...row, title: row.title ?? row.sessionTitle ?? null }));
|
|
1830
|
+
return { data, total: body?.total };
|
|
1831
|
+
}
|
|
1832
|
+
function defaultParseMessages(json) {
|
|
1833
|
+
const body = json;
|
|
1834
|
+
return { data: Array.isArray(body?.data) ? body.data : [] };
|
|
1835
|
+
}
|
|
1836
|
+
function withQuery(path, params) {
|
|
1837
|
+
const qs = Object.entries(params).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
|
|
1838
|
+
if (!qs) return path;
|
|
1839
|
+
return `${path}${path.includes("?") ? "&" : "?"}${qs}`;
|
|
1840
|
+
}
|
|
1841
|
+
function toFeedbackState(feedback) {
|
|
1842
|
+
const value = feedback?.feedback;
|
|
1843
|
+
if (!value) return null;
|
|
1844
|
+
return value === "POSITIVE" ? "up" : "down";
|
|
1845
|
+
}
|
|
1846
|
+
function toMessageDisplay(rows, sessionId) {
|
|
1847
|
+
return rows.flatMap((row) => {
|
|
1848
|
+
const timestamp = row.startTime || row.endTime || (/* @__PURE__ */ new Date()).toISOString();
|
|
1849
|
+
const out = [
|
|
1850
|
+
{
|
|
1851
|
+
id: `${row.id}:user`,
|
|
1852
|
+
sessionId,
|
|
1853
|
+
role: "user",
|
|
1854
|
+
content: row.sessionUserIntent,
|
|
1855
|
+
timestamp
|
|
1856
|
+
}
|
|
1857
|
+
];
|
|
1858
|
+
if (row.agentResponse) {
|
|
1859
|
+
out.push({
|
|
1860
|
+
id: `${row.id}:assistant`,
|
|
1861
|
+
sessionId,
|
|
1862
|
+
role: "assistant",
|
|
1863
|
+
content: row.agentResponse,
|
|
1864
|
+
timestamp: row.endTime || timestamp,
|
|
1865
|
+
executionId: row.id,
|
|
1866
|
+
isError: row.status === "FAILED",
|
|
1867
|
+
feedback: toFeedbackState(row.feedback)
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
return out;
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
function useChatSessions({
|
|
1874
|
+
api,
|
|
1875
|
+
sessions,
|
|
1876
|
+
initialSessionId
|
|
1877
|
+
}) {
|
|
1878
|
+
const enabled = sessions?.enabled === true;
|
|
1879
|
+
const listEndpoint = sessions?.listEndpoint ?? "/api/conversations/sessions";
|
|
1880
|
+
const messagesEndpointTemplate = sessions?.messagesEndpoint ?? "/api/conversations/sessions/{sessionId}/messages";
|
|
1881
|
+
const pageSize = sessions?.pageSize ?? DEFAULT_PAGE_SIZE;
|
|
1882
|
+
const messagesPageSize = sessions?.messagesPageSize ?? DEFAULT_MESSAGES_PAGE_SIZE;
|
|
1883
|
+
const parseSessionsResponse = sessions?.parseSessionsResponse ?? defaultParseSessions;
|
|
1884
|
+
const parseMessagesResponse = sessions?.parseMessagesResponse ?? defaultParseMessages;
|
|
1885
|
+
const [sessionsList, setSessionsList] = React.useState([]);
|
|
1886
|
+
const [isLoadingList, setIsLoadingList] = React.useState(enabled);
|
|
1887
|
+
const [isLoadingMore, setIsLoadingMore] = React.useState(false);
|
|
1888
|
+
const [listError, setListError] = React.useState(null);
|
|
1889
|
+
const hasLoadedOnceRef = React.useRef(false);
|
|
1890
|
+
const [page, setPage] = React.useState(0);
|
|
1891
|
+
const [total, setTotal] = React.useState(null);
|
|
1892
|
+
const [lastPageFull, setLastPageFull] = React.useState(false);
|
|
1893
|
+
const [selectedSessionId, setSelectedSessionId] = React.useState(
|
|
1894
|
+
initialSessionId ?? null
|
|
1895
|
+
);
|
|
1896
|
+
const [draftSessionId, setDraftSessionId] = React.useState(generateId);
|
|
1897
|
+
const [selectedMessages, setSelectedMessages] = React.useState([]);
|
|
1898
|
+
const [isLoadingMessages, setIsLoadingMessages] = React.useState(
|
|
1899
|
+
enabled && initialSessionId != null
|
|
1900
|
+
);
|
|
1901
|
+
const [messagesError, setMessagesError] = React.useState(null);
|
|
1902
|
+
const [refetchTick, setRefetchTick] = React.useState(0);
|
|
1903
|
+
const baseUrl = (api.baseUrl || "").replace(/\/+$/, "");
|
|
1904
|
+
const apiHeaders = api.headers;
|
|
1905
|
+
const authToken = api.authToken;
|
|
1906
|
+
const headersKey = JSON.stringify(apiHeaders ?? {});
|
|
1907
|
+
const requestHeaders = React.useMemo(() => {
|
|
1908
|
+
const headers = { Accept: "application/json", ...apiHeaders ?? {} };
|
|
1909
|
+
if (authToken && !headers.Authorization) headers.Authorization = `Bearer ${authToken}`;
|
|
1910
|
+
return headers;
|
|
1911
|
+
}, [headersKey, authToken]);
|
|
1912
|
+
const hasMore = total != null ? sessionsList.length < total : lastPageFull;
|
|
1913
|
+
React.useEffect(() => {
|
|
1914
|
+
setPage(0);
|
|
1915
|
+
hasLoadedOnceRef.current = false;
|
|
1916
|
+
}, [enabled, baseUrl, listEndpoint, pageSize, requestHeaders]);
|
|
1917
|
+
React.useEffect(() => {
|
|
1918
|
+
setPage(0);
|
|
1919
|
+
}, [refetchTick]);
|
|
1920
|
+
React.useEffect(() => {
|
|
1921
|
+
if (!enabled) return;
|
|
1922
|
+
const ctrl = new AbortController();
|
|
1923
|
+
const isFirstPage = page === 0;
|
|
1924
|
+
if (isFirstPage && !hasLoadedOnceRef.current) setIsLoadingList(true);
|
|
1925
|
+
else if (!isFirstPage) setIsLoadingMore(true);
|
|
1926
|
+
setListError(null);
|
|
1927
|
+
fetch(withQuery(`${baseUrl}${listEndpoint}`, { page, limit: pageSize }), {
|
|
1928
|
+
method: "GET",
|
|
1929
|
+
headers: requestHeaders,
|
|
1930
|
+
signal: ctrl.signal
|
|
1931
|
+
}).then(async (res) => {
|
|
1932
|
+
if (!res.ok) throw new Error(`Failed to load chats (${res.status})`);
|
|
1933
|
+
return res.json();
|
|
1934
|
+
}).then((json) => {
|
|
1935
|
+
const parsed = parseSessionsResponse(json);
|
|
1936
|
+
setSessionsList((prev) => isFirstPage ? parsed.data : [...prev, ...parsed.data]);
|
|
1937
|
+
setTotal(parsed.total ?? null);
|
|
1938
|
+
setLastPageFull(parsed.data.length >= pageSize);
|
|
1939
|
+
hasLoadedOnceRef.current = true;
|
|
1940
|
+
}).catch((e) => {
|
|
1941
|
+
if (e.name === "AbortError") return;
|
|
1942
|
+
setListError(e instanceof Error ? e.message : "Failed to load chats");
|
|
1943
|
+
}).finally(() => {
|
|
1944
|
+
setIsLoadingList(false);
|
|
1945
|
+
setIsLoadingMore(false);
|
|
1946
|
+
});
|
|
1947
|
+
return () => ctrl.abort();
|
|
1948
|
+
}, [enabled, baseUrl, listEndpoint, pageSize, requestHeaders, refetchTick, page]);
|
|
1949
|
+
React.useEffect(() => {
|
|
1950
|
+
if (!enabled || !selectedSessionId) {
|
|
1951
|
+
setSelectedMessages([]);
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
const ctrl = new AbortController();
|
|
1955
|
+
setIsLoadingMessages(true);
|
|
1956
|
+
setMessagesError(null);
|
|
1957
|
+
const path = messagesEndpointTemplate.replace(
|
|
1958
|
+
"{sessionId}",
|
|
1959
|
+
encodeURIComponent(selectedSessionId)
|
|
1960
|
+
);
|
|
1961
|
+
fetch(withQuery(`${baseUrl}${path}`, { limit: messagesPageSize }), {
|
|
1962
|
+
method: "GET",
|
|
1963
|
+
headers: requestHeaders,
|
|
1964
|
+
signal: ctrl.signal
|
|
1965
|
+
}).then(async (res) => {
|
|
1966
|
+
if (!res.ok) throw new Error(`Failed to load messages (${res.status})`);
|
|
1967
|
+
return res.json();
|
|
1968
|
+
}).then(
|
|
1969
|
+
(json) => setSelectedMessages(
|
|
1970
|
+
toMessageDisplay(parseMessagesResponse(json).data, selectedSessionId)
|
|
1971
|
+
)
|
|
1972
|
+
).catch((e) => {
|
|
1973
|
+
if (e.name === "AbortError") return;
|
|
1974
|
+
setMessagesError(e instanceof Error ? e.message : "Failed to load messages");
|
|
1975
|
+
setSelectedMessages([]);
|
|
1976
|
+
}).finally(() => setIsLoadingMessages(false));
|
|
1977
|
+
return () => ctrl.abort();
|
|
1978
|
+
}, [enabled, selectedSessionId, baseUrl, messagesEndpointTemplate, messagesPageSize, requestHeaders]);
|
|
1979
|
+
const loadMore = React.useCallback(() => {
|
|
1980
|
+
setPage((prev) => {
|
|
1981
|
+
if (isLoadingList || isLoadingMore || !hasMore) return prev;
|
|
1982
|
+
return prev + 1;
|
|
1983
|
+
});
|
|
1984
|
+
}, [isLoadingList, isLoadingMore, hasMore]);
|
|
1985
|
+
const selectSession = React.useCallback((sessionId) => {
|
|
1986
|
+
setSelectedSessionId(sessionId);
|
|
1987
|
+
setSelectedMessages([]);
|
|
1988
|
+
}, []);
|
|
1989
|
+
const startNewSession = React.useCallback(() => {
|
|
1990
|
+
setSelectedSessionId(null);
|
|
1991
|
+
setDraftSessionId(generateId());
|
|
1992
|
+
setSelectedMessages([]);
|
|
1993
|
+
}, []);
|
|
1994
|
+
const refetch = React.useCallback(() => setRefetchTick((tick) => tick + 1), []);
|
|
1995
|
+
const noteSentMessage = React.useCallback(
|
|
1996
|
+
(text) => {
|
|
1997
|
+
const id = selectedSessionId ?? draftSessionId;
|
|
1998
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1999
|
+
const trimmed = text.trim();
|
|
2000
|
+
setSessionsList((prev) => {
|
|
2001
|
+
const idx = prev.findIndex((s) => s.sessionId === id);
|
|
2002
|
+
if (idx >= 0) {
|
|
2003
|
+
const existing = prev[idx];
|
|
2004
|
+
const bumped = {
|
|
2005
|
+
...existing,
|
|
2006
|
+
lastMessageAt: now,
|
|
2007
|
+
messageCount: (existing.messageCount ?? 0) + 1,
|
|
2008
|
+
title: existing.title?.trim() ? existing.title : trimmed
|
|
2009
|
+
};
|
|
2010
|
+
return [bumped, ...prev.slice(0, idx), ...prev.slice(idx + 1)];
|
|
2011
|
+
}
|
|
2012
|
+
const fresh = {
|
|
2013
|
+
sessionId: id,
|
|
2014
|
+
title: trimmed,
|
|
2015
|
+
messageCount: 1,
|
|
2016
|
+
lastMessageAt: now,
|
|
2017
|
+
status: "PROCESSING"
|
|
2018
|
+
};
|
|
2019
|
+
return [fresh, ...prev];
|
|
2020
|
+
});
|
|
2021
|
+
},
|
|
2022
|
+
[selectedSessionId, draftSessionId]
|
|
2023
|
+
);
|
|
2024
|
+
return {
|
|
2025
|
+
enabled,
|
|
2026
|
+
sessionsList,
|
|
2027
|
+
isLoadingList,
|
|
2028
|
+
listError,
|
|
2029
|
+
total,
|
|
2030
|
+
hasMore,
|
|
2031
|
+
isLoadingMore,
|
|
2032
|
+
loadMore,
|
|
2033
|
+
noteSentMessage,
|
|
2034
|
+
selectedSessionId,
|
|
2035
|
+
activeSessionId: selectedSessionId ?? draftSessionId,
|
|
2036
|
+
selectSession,
|
|
2037
|
+
startNewSession,
|
|
2038
|
+
selectedMessages,
|
|
2039
|
+
isLoadingMessages,
|
|
2040
|
+
messagesError,
|
|
2041
|
+
refetch
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
function deriveStatus(enabled, blocked) {
|
|
2045
|
+
if (blocked === true) return "blocked";
|
|
2046
|
+
if (enabled === false) return "disabled";
|
|
2047
|
+
if (enabled === true) return "available";
|
|
2048
|
+
return "unknown";
|
|
2049
|
+
}
|
|
2050
|
+
function defaultParse(json) {
|
|
2051
|
+
const body = json;
|
|
2052
|
+
return {
|
|
2053
|
+
available: body?.enabled === true && body?.blocked !== true,
|
|
2054
|
+
status: deriveStatus(body?.enabled, body?.blocked),
|
|
2055
|
+
config: body ?? void 0
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
2058
|
+
function useAgentConfig({ api, availability }) {
|
|
2059
|
+
const enabled = availability?.enabled === true;
|
|
2060
|
+
const endpoint = availability?.endpoint ?? "/api/agent/config";
|
|
2061
|
+
const parseResponse = availability?.parseResponse ?? defaultParse;
|
|
2062
|
+
const [available, setAvailable] = React.useState(null);
|
|
2063
|
+
const [status, setStatus] = React.useState("unknown");
|
|
2064
|
+
const [config, setConfig] = React.useState(void 0);
|
|
2065
|
+
const [isLoading, setIsLoading] = React.useState(enabled);
|
|
2066
|
+
const [error, setError] = React.useState(null);
|
|
2067
|
+
const [refetchTick, setRefetchTick] = React.useState(0);
|
|
2068
|
+
const baseUrl = (api.baseUrl || "").replace(/\/+$/, "");
|
|
2069
|
+
const apiHeaders = api.headers;
|
|
2070
|
+
const authToken = api.authToken;
|
|
2071
|
+
const requestHeaders = React.useMemo(() => {
|
|
2072
|
+
const headers = { Accept: "application/json", ...apiHeaders ?? {} };
|
|
2073
|
+
if (authToken && !headers.Authorization) headers.Authorization = `Bearer ${authToken}`;
|
|
2074
|
+
return headers;
|
|
2075
|
+
}, [apiHeaders, authToken]);
|
|
2076
|
+
React.useEffect(() => {
|
|
2077
|
+
if (!enabled) return;
|
|
2078
|
+
const ctrl = new AbortController();
|
|
2079
|
+
setIsLoading(true);
|
|
2080
|
+
setError(null);
|
|
2081
|
+
fetch(`${baseUrl}${endpoint}`, {
|
|
2082
|
+
method: "GET",
|
|
2083
|
+
headers: requestHeaders,
|
|
2084
|
+
signal: ctrl.signal
|
|
2085
|
+
}).then(async (res) => {
|
|
2086
|
+
if (!res.ok) throw new Error(`Failed to check availability (${res.status})`);
|
|
2087
|
+
return res.json();
|
|
2088
|
+
}).then((json) => {
|
|
2089
|
+
const parsed = parseResponse(json);
|
|
2090
|
+
setAvailable(parsed.available);
|
|
2091
|
+
setStatus(parsed.status ?? deriveStatus(parsed.available, void 0));
|
|
2092
|
+
setConfig(parsed.config);
|
|
2093
|
+
}).catch((e) => {
|
|
2094
|
+
if (e.name === "AbortError") return;
|
|
2095
|
+
setError(e instanceof Error ? e.message : "Failed to check availability");
|
|
2096
|
+
}).finally(() => setIsLoading(false));
|
|
2097
|
+
return () => ctrl.abort();
|
|
2098
|
+
}, [enabled, baseUrl, endpoint, requestHeaders, refetchTick]);
|
|
2099
|
+
const refetch = React.useCallback(() => setRefetchTick((tick) => tick + 1), []);
|
|
2100
|
+
return { enabled, available, status, config, isLoading, error, refetch };
|
|
2101
|
+
}
|
|
1786
2102
|
function classifyField(field) {
|
|
1787
2103
|
if (!field) return "text";
|
|
1788
2104
|
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
@@ -3239,11 +3555,10 @@ function UserMessageV2({
|
|
|
3239
3555
|
),
|
|
3240
3556
|
style: { borderRadius: 9999 },
|
|
3241
3557
|
children: [
|
|
3242
|
-
toast.tone === "success" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {
|
|
3558
|
+
toast.tone === "success" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { style: { width: 14, height: 14, color: "#059669" } }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3243
3559
|
lucideReact.AlertCircle,
|
|
3244
3560
|
{
|
|
3245
|
-
|
|
3246
|
-
style: { color: "#ef4444" }
|
|
3561
|
+
style: { width: 14, height: 14, color: "#ef4444" }
|
|
3247
3562
|
}
|
|
3248
3563
|
),
|
|
3249
3564
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: toast.label })
|
|
@@ -3267,8 +3582,13 @@ function UserMessageV2({
|
|
|
3267
3582
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3268
3583
|
lucideReact.AlertCircle,
|
|
3269
3584
|
{
|
|
3270
|
-
|
|
3271
|
-
|
|
3585
|
+
style: {
|
|
3586
|
+
width: 14,
|
|
3587
|
+
height: 14,
|
|
3588
|
+
flexShrink: 0,
|
|
3589
|
+
color: "rgba(239, 68, 68, 0.7)",
|
|
3590
|
+
marginTop: "2px"
|
|
3591
|
+
}
|
|
3272
3592
|
}
|
|
3273
3593
|
),
|
|
3274
3594
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-user-msg-error-text", children: resolvedError })
|
|
@@ -3286,10 +3606,9 @@ function UserMessageV2({
|
|
|
3286
3606
|
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3287
3607
|
lucideReact.Check,
|
|
3288
3608
|
{
|
|
3289
|
-
|
|
3290
|
-
style: { color: "#059669" }
|
|
3609
|
+
style: { width: 14, height: 14, color: "#059669" }
|
|
3291
3610
|
}
|
|
3292
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, {
|
|
3611
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { style: { width: 14, height: 14 } })
|
|
3293
3612
|
}
|
|
3294
3613
|
) }),
|
|
3295
3614
|
showEditAction && onEdit && /* @__PURE__ */ jsxRuntime.jsx(ActionTooltipV2, { label: "Edit", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3299,7 +3618,7 @@ function UserMessageV2({
|
|
|
3299
3618
|
onClick: () => onEdit(message.id),
|
|
3300
3619
|
className: "payman-v2-user-msg-action-btn",
|
|
3301
3620
|
"aria-label": "Edit message",
|
|
3302
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, {
|
|
3621
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { style: { width: 14, height: 14 } })
|
|
3303
3622
|
}
|
|
3304
3623
|
) }),
|
|
3305
3624
|
showRetryAction && onRetry && /* @__PURE__ */ jsxRuntime.jsx(ActionTooltipV2, { label: "Retry", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3310,7 +3629,7 @@ function UserMessageV2({
|
|
|
3310
3629
|
disabled: retryDisabled,
|
|
3311
3630
|
className: "payman-v2-user-msg-action-btn",
|
|
3312
3631
|
"aria-label": "Retry message",
|
|
3313
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, {
|
|
3632
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { style: { width: 14, height: 14 } })
|
|
3314
3633
|
}
|
|
3315
3634
|
) })
|
|
3316
3635
|
] })
|
|
@@ -4109,6 +4428,8 @@ function AssistantMessageV2({
|
|
|
4109
4428
|
void 0,
|
|
4110
4429
|
typingSpeed
|
|
4111
4430
|
);
|
|
4431
|
+
const displayContentPending = Boolean(rawResponseContent) && !displayContent;
|
|
4432
|
+
const showThinkingBlock = isThinkingStreaming || displayContentPending;
|
|
4112
4433
|
const stickyLabel = (() => {
|
|
4113
4434
|
const steps = message.steps;
|
|
4114
4435
|
if (!steps || steps.length === 0) return void 0;
|
|
@@ -4222,14 +4543,12 @@ function AssistantMessageV2({
|
|
|
4222
4543
|
toast.tone === "success" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4223
4544
|
lucideReact.Check,
|
|
4224
4545
|
{
|
|
4225
|
-
|
|
4226
|
-
style: { color: "#059669" }
|
|
4546
|
+
style: { width: 14, height: 14, color: "#059669" }
|
|
4227
4547
|
}
|
|
4228
4548
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4229
4549
|
lucideReact.AlertCircle,
|
|
4230
4550
|
{
|
|
4231
|
-
|
|
4232
|
-
style: { color: "#ef4444" }
|
|
4551
|
+
style: { width: 14, height: 14, color: "#ef4444" }
|
|
4233
4552
|
}
|
|
4234
4553
|
),
|
|
4235
4554
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: toast.label })
|
|
@@ -4243,7 +4562,7 @@ function AssistantMessageV2({
|
|
|
4243
4562
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4244
4563
|
toastPortal,
|
|
4245
4564
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: [
|
|
4246
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children:
|
|
4565
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showThinkingBlock && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4247
4566
|
framerMotion.motion.div,
|
|
4248
4567
|
{
|
|
4249
4568
|
initial: { opacity: 0, height: 0 },
|
|
@@ -4273,6 +4592,10 @@ function AssistantMessageV2({
|
|
|
4273
4592
|
isResolvingImages: message.isResolvingImages,
|
|
4274
4593
|
onImageClick
|
|
4275
4594
|
}
|
|
4595
|
+
) : displayContentPending ? (
|
|
4596
|
+
// The intent/status line above is still bridging this
|
|
4597
|
+
// gap (see `showThinkingBlock`) — nothing to add here.
|
|
4598
|
+
null
|
|
4276
4599
|
) : !isThinkingStreaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
|
|
4277
4600
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showTrailingProgress && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4278
4601
|
framerMotion.motion.div,
|
|
@@ -4393,6 +4716,112 @@ function AssistantMessageV2({
|
|
|
4393
4716
|
)
|
|
4394
4717
|
] });
|
|
4395
4718
|
}
|
|
4719
|
+
var CHAR_VARIANTS = {
|
|
4720
|
+
fade: {
|
|
4721
|
+
initial: { opacity: 0, scale: 0.7 },
|
|
4722
|
+
animate: { opacity: 1, scale: 1 },
|
|
4723
|
+
exit: { opacity: 0, scale: 0.7 },
|
|
4724
|
+
transition: { duration: 0.14, ease: "easeOut" },
|
|
4725
|
+
overflow: "hidden"
|
|
4726
|
+
},
|
|
4727
|
+
blur: {
|
|
4728
|
+
initial: { opacity: 0, filter: "blur(8px)", y: -8 },
|
|
4729
|
+
animate: { opacity: 1, filter: "blur(0px)", y: 0 },
|
|
4730
|
+
exit: { opacity: 0, filter: "blur(8px)", y: 8 },
|
|
4731
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
4732
|
+
overflow: "visible"
|
|
4733
|
+
}
|
|
4734
|
+
};
|
|
4735
|
+
function CharSlot({
|
|
4736
|
+
char,
|
|
4737
|
+
charKey,
|
|
4738
|
+
effect
|
|
4739
|
+
}) {
|
|
4740
|
+
if (!/\d/.test(char)) return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block" }, children: char });
|
|
4741
|
+
const v = CHAR_VARIANTS[effect];
|
|
4742
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { position: "relative", display: "inline-block", overflow: v.overflow }, children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4743
|
+
framerMotion.motion.span,
|
|
4744
|
+
{
|
|
4745
|
+
initial: v.initial,
|
|
4746
|
+
animate: v.animate,
|
|
4747
|
+
exit: v.exit,
|
|
4748
|
+
transition: v.transition,
|
|
4749
|
+
style: { display: "inline-block" },
|
|
4750
|
+
children: char
|
|
4751
|
+
},
|
|
4752
|
+
charKey
|
|
4753
|
+
) }) });
|
|
4754
|
+
}
|
|
4755
|
+
function CountUp({
|
|
4756
|
+
to,
|
|
4757
|
+
from = 0,
|
|
4758
|
+
duration = 2,
|
|
4759
|
+
delay = 0,
|
|
4760
|
+
digitEffect = "none",
|
|
4761
|
+
className,
|
|
4762
|
+
startWhen = true,
|
|
4763
|
+
separator = ""
|
|
4764
|
+
}) {
|
|
4765
|
+
const ref = React.useRef(null);
|
|
4766
|
+
const motionValue = framerMotion.useMotionValue(from);
|
|
4767
|
+
const damping = 20 + 40 * (1 / duration);
|
|
4768
|
+
const stiffness = 100 * (1 / duration);
|
|
4769
|
+
const springValue = framerMotion.useSpring(motionValue, { damping, stiffness });
|
|
4770
|
+
const isInView = framerMotion.useInView(ref, { once: true, margin: "0px" });
|
|
4771
|
+
const decimals = React.useMemo(() => {
|
|
4772
|
+
const d = (n) => {
|
|
4773
|
+
const s = n.toString();
|
|
4774
|
+
return s.includes(".") ? s.split(".")[1].length : 0;
|
|
4775
|
+
};
|
|
4776
|
+
return Math.max(d(from), d(to));
|
|
4777
|
+
}, [from, to]);
|
|
4778
|
+
const formatValue = React.useCallback(
|
|
4779
|
+
(latest) => {
|
|
4780
|
+
const formatted = Intl.NumberFormat("en-US", {
|
|
4781
|
+
useGrouping: !!separator,
|
|
4782
|
+
minimumFractionDigits: decimals,
|
|
4783
|
+
maximumFractionDigits: decimals
|
|
4784
|
+
}).format(latest);
|
|
4785
|
+
return separator ? formatted.replace(/,/g, separator) : formatted;
|
|
4786
|
+
},
|
|
4787
|
+
[decimals, separator]
|
|
4788
|
+
);
|
|
4789
|
+
const [chars, setChars] = React.useState(formatValue(from).split(""));
|
|
4790
|
+
React.useEffect(() => {
|
|
4791
|
+
if (isInView && startWhen) {
|
|
4792
|
+
const t = setTimeout(() => motionValue.set(to), delay * 1e3);
|
|
4793
|
+
return () => clearTimeout(t);
|
|
4794
|
+
}
|
|
4795
|
+
}, [isInView, startWhen, motionValue, to, delay]);
|
|
4796
|
+
React.useEffect(() => {
|
|
4797
|
+
const unsub = springValue.on("change", (latest) => {
|
|
4798
|
+
if (digitEffect === "none") {
|
|
4799
|
+
if (ref.current) ref.current.textContent = formatValue(latest);
|
|
4800
|
+
} else {
|
|
4801
|
+
setChars(formatValue(latest).split(""));
|
|
4802
|
+
}
|
|
4803
|
+
});
|
|
4804
|
+
return () => unsub();
|
|
4805
|
+
}, [springValue, formatValue, digitEffect]);
|
|
4806
|
+
if (digitEffect === "none") {
|
|
4807
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn(className), children: formatValue(from) });
|
|
4808
|
+
}
|
|
4809
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("inline-flex items-center", className), children: chars.map((char, i) => /* @__PURE__ */ jsxRuntime.jsx(CharSlot, { char, charKey: `${i}-${char}`, effect: digitEffect }, i)) });
|
|
4810
|
+
}
|
|
4811
|
+
function AnimatedDuration({ seconds, className }) {
|
|
4812
|
+
const total = Math.max(0, seconds);
|
|
4813
|
+
const m = Math.floor(total / 60);
|
|
4814
|
+
const s = total % 60;
|
|
4815
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("tabular-nums", className), children: [
|
|
4816
|
+
m > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4817
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountUp, { to: m, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4818
|
+
"m",
|
|
4819
|
+
" "
|
|
4820
|
+
] }),
|
|
4821
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountUp, { to: s, duration: 0.9, digitEffect: "blur", className: "tabular-nums" }),
|
|
4822
|
+
"s"
|
|
4823
|
+
] });
|
|
4824
|
+
}
|
|
4396
4825
|
var DEFAULT_MAX_LENGTH = 6;
|
|
4397
4826
|
var MAX_SUPPORTED_LENGTH = 12;
|
|
4398
4827
|
var AUTO_FOCUS_DELAY_MS = 250;
|
|
@@ -4519,7 +4948,6 @@ function VerificationInline({
|
|
|
4519
4948
|
React.useEffect(() => {
|
|
4520
4949
|
if (prompt.subAction === "SubmissionInvalid") {
|
|
4521
4950
|
setErrored(true);
|
|
4522
|
-
setCode("");
|
|
4523
4951
|
lastSubmittedRef.current = null;
|
|
4524
4952
|
}
|
|
4525
4953
|
}, [prompt.subAction, prompt.userActionId]);
|
|
@@ -4598,7 +5026,7 @@ function VerificationInline({
|
|
|
4598
5026
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4599
5027
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "payman-v2-ua-icon", size: 15, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4600
5028
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-title", children: "Verification required" }),
|
|
4601
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
5029
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsxRuntime.jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4602
5030
|
] }),
|
|
4603
5031
|
renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRendererV2, { content: description }) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: description }),
|
|
4604
5032
|
stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -4670,6 +5098,228 @@ function VerificationInline({
|
|
|
4670
5098
|
] })
|
|
4671
5099
|
] });
|
|
4672
5100
|
}
|
|
5101
|
+
function AmountFieldV2({
|
|
5102
|
+
id,
|
|
5103
|
+
value,
|
|
5104
|
+
onChange,
|
|
5105
|
+
disabled,
|
|
5106
|
+
className,
|
|
5107
|
+
onEnter
|
|
5108
|
+
}) {
|
|
5109
|
+
const inputRef = React.useRef(null);
|
|
5110
|
+
const digits = digitsFromValue(value);
|
|
5111
|
+
const display = formatDigits(digits);
|
|
5112
|
+
React.useLayoutEffect(() => {
|
|
5113
|
+
const el = inputRef.current;
|
|
5114
|
+
if (el && document.activeElement === el) {
|
|
5115
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
5116
|
+
}
|
|
5117
|
+
}, [display]);
|
|
5118
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5119
|
+
"input",
|
|
5120
|
+
{
|
|
5121
|
+
ref: inputRef,
|
|
5122
|
+
id,
|
|
5123
|
+
type: "text",
|
|
5124
|
+
inputMode: "decimal",
|
|
5125
|
+
autoComplete: "off",
|
|
5126
|
+
className,
|
|
5127
|
+
value: display,
|
|
5128
|
+
placeholder: "0.00",
|
|
5129
|
+
disabled,
|
|
5130
|
+
onChange: (e) => {
|
|
5131
|
+
onChange(valueFromDigits(digitsFromDisplay(e.target.value)));
|
|
5132
|
+
},
|
|
5133
|
+
onKeyDown: (e) => {
|
|
5134
|
+
if (e.key === "Enter") {
|
|
5135
|
+
e.preventDefault();
|
|
5136
|
+
onEnter?.();
|
|
5137
|
+
}
|
|
5138
|
+
},
|
|
5139
|
+
onFocus: (e) => {
|
|
5140
|
+
const el = e.currentTarget;
|
|
5141
|
+
requestAnimationFrame(() => el.setSelectionRange(el.value.length, el.value.length));
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
);
|
|
5145
|
+
}
|
|
5146
|
+
function digitsFromDisplay(raw) {
|
|
5147
|
+
return raw.replace(/[^0-9]/g, "").replace(/^0+(?=\d)/, "").slice(-9);
|
|
5148
|
+
}
|
|
5149
|
+
function digitsFromValue(value) {
|
|
5150
|
+
const num = Number(value);
|
|
5151
|
+
if (!value || !Number.isFinite(num) || num <= 0) return "";
|
|
5152
|
+
return String(Math.round(num * 100));
|
|
5153
|
+
}
|
|
5154
|
+
function formatDigits(digits) {
|
|
5155
|
+
if (!digits) return "";
|
|
5156
|
+
const padded = digits.padStart(3, "0");
|
|
5157
|
+
const cents = padded.slice(-2);
|
|
5158
|
+
const whole = padded.slice(0, -2).replace(/^0+(?=\d)/, "") || "0";
|
|
5159
|
+
const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
5160
|
+
return `${grouped}.${cents}`;
|
|
5161
|
+
}
|
|
5162
|
+
function valueFromDigits(digits) {
|
|
5163
|
+
if (!digits) return "";
|
|
5164
|
+
return (Number(digits) / 100).toString();
|
|
5165
|
+
}
|
|
5166
|
+
function findRootClassName(el) {
|
|
5167
|
+
const root = el?.closest(".payman-v2-root");
|
|
5168
|
+
return root instanceof HTMLElement ? root.className : "";
|
|
5169
|
+
}
|
|
5170
|
+
var MENU_MAX_HEIGHT = 240;
|
|
5171
|
+
var OPTION_HEIGHT = 34;
|
|
5172
|
+
var VIEWPORT_MARGIN = 8;
|
|
5173
|
+
function SelectFieldV2({
|
|
5174
|
+
id,
|
|
5175
|
+
value,
|
|
5176
|
+
options,
|
|
5177
|
+
onChange,
|
|
5178
|
+
disabled,
|
|
5179
|
+
error,
|
|
5180
|
+
placeholder = "Select\u2026"
|
|
5181
|
+
}) {
|
|
5182
|
+
const triggerRef = React.useRef(null);
|
|
5183
|
+
const listRef = React.useRef(null);
|
|
5184
|
+
const [open, setOpen] = React.useState(false);
|
|
5185
|
+
const [rect, setRect] = React.useState(null);
|
|
5186
|
+
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
5187
|
+
const [rootClassName, setRootClassName] = React.useState("");
|
|
5188
|
+
const selected = options.find((o) => o.const === value);
|
|
5189
|
+
React.useLayoutEffect(() => {
|
|
5190
|
+
if (!open) return;
|
|
5191
|
+
const place = () => {
|
|
5192
|
+
const el = triggerRef.current;
|
|
5193
|
+
if (!el) return;
|
|
5194
|
+
const r = el.getBoundingClientRect();
|
|
5195
|
+
const viewportH = window.innerHeight;
|
|
5196
|
+
const estimatedMenuH = Math.min(
|
|
5197
|
+
options.length * OPTION_HEIGHT + VIEWPORT_MARGIN,
|
|
5198
|
+
MENU_MAX_HEIGHT
|
|
5199
|
+
);
|
|
5200
|
+
const spaceBelow = viewportH - r.bottom;
|
|
5201
|
+
const spaceAbove = r.top;
|
|
5202
|
+
const openUp = spaceBelow < estimatedMenuH && spaceAbove > spaceBelow;
|
|
5203
|
+
setRect({ top: r.bottom, bottom: viewportH - r.top, left: r.left, width: r.width, openUp });
|
|
5204
|
+
setRootClassName(findRootClassName(el));
|
|
5205
|
+
};
|
|
5206
|
+
place();
|
|
5207
|
+
window.addEventListener("resize", place);
|
|
5208
|
+
window.addEventListener("scroll", place, true);
|
|
5209
|
+
return () => {
|
|
5210
|
+
window.removeEventListener("resize", place);
|
|
5211
|
+
window.removeEventListener("scroll", place, true);
|
|
5212
|
+
};
|
|
5213
|
+
}, [open, options.length]);
|
|
5214
|
+
React.useEffect(() => {
|
|
5215
|
+
if (!open) return;
|
|
5216
|
+
setActiveIndex(Math.max(0, options.findIndex((o) => o.const === value)));
|
|
5217
|
+
listRef.current?.focus();
|
|
5218
|
+
}, [open]);
|
|
5219
|
+
React.useEffect(() => {
|
|
5220
|
+
if (!open) return;
|
|
5221
|
+
const onDocDown = (e) => {
|
|
5222
|
+
const target = e.target;
|
|
5223
|
+
if (triggerRef.current?.contains(target) || listRef.current?.contains(target)) return;
|
|
5224
|
+
setOpen(false);
|
|
5225
|
+
};
|
|
5226
|
+
document.addEventListener("mousedown", onDocDown);
|
|
5227
|
+
return () => document.removeEventListener("mousedown", onDocDown);
|
|
5228
|
+
}, [open]);
|
|
5229
|
+
const commit = (opt) => {
|
|
5230
|
+
onChange(opt.const);
|
|
5231
|
+
setOpen(false);
|
|
5232
|
+
triggerRef.current?.focus();
|
|
5233
|
+
};
|
|
5234
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5235
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5236
|
+
"button",
|
|
5237
|
+
{
|
|
5238
|
+
ref: triggerRef,
|
|
5239
|
+
id,
|
|
5240
|
+
type: "button",
|
|
5241
|
+
disabled,
|
|
5242
|
+
className: cn("payman-v2-ua-select-trigger", error && "payman-v2-ua-input-error"),
|
|
5243
|
+
"aria-haspopup": "listbox",
|
|
5244
|
+
"aria-expanded": open,
|
|
5245
|
+
onClick: () => setOpen((v) => !v),
|
|
5246
|
+
onKeyDown: (e) => {
|
|
5247
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
5248
|
+
e.preventDefault();
|
|
5249
|
+
setOpen(true);
|
|
5250
|
+
}
|
|
5251
|
+
},
|
|
5252
|
+
children: [
|
|
5253
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5254
|
+
"span",
|
|
5255
|
+
{
|
|
5256
|
+
className: cn(
|
|
5257
|
+
"payman-v2-ua-select-value",
|
|
5258
|
+
!selected && "payman-v2-ua-select-placeholder"
|
|
5259
|
+
),
|
|
5260
|
+
children: selected ? selected.title || selected.const : placeholder
|
|
5261
|
+
}
|
|
5262
|
+
),
|
|
5263
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14, className: "payman-v2-ua-select-chevron", "aria-hidden": true })
|
|
5264
|
+
]
|
|
5265
|
+
}
|
|
5266
|
+
),
|
|
5267
|
+
open && rect && typeof document !== "undefined" && reactDom.createPortal(
|
|
5268
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5269
|
+
"div",
|
|
5270
|
+
{
|
|
5271
|
+
ref: listRef,
|
|
5272
|
+
role: "listbox",
|
|
5273
|
+
className: cn(rootClassName, "payman-v2-ua-select-menu"),
|
|
5274
|
+
tabIndex: -1,
|
|
5275
|
+
style: {
|
|
5276
|
+
position: "fixed",
|
|
5277
|
+
left: rect.left,
|
|
5278
|
+
width: rect.width,
|
|
5279
|
+
height: "fit-content",
|
|
5280
|
+
maxHeight: MENU_MAX_HEIGHT,
|
|
5281
|
+
...rect.openUp ? { bottom: rect.bottom } : { top: rect.top }
|
|
5282
|
+
},
|
|
5283
|
+
onKeyDown: (e) => {
|
|
5284
|
+
if (e.key === "ArrowDown") {
|
|
5285
|
+
e.preventDefault();
|
|
5286
|
+
setActiveIndex((i) => Math.min(options.length - 1, i + 1));
|
|
5287
|
+
} else if (e.key === "ArrowUp") {
|
|
5288
|
+
e.preventDefault();
|
|
5289
|
+
setActiveIndex((i) => Math.max(0, i - 1));
|
|
5290
|
+
} else if (e.key === "Enter" || e.key === " ") {
|
|
5291
|
+
e.preventDefault();
|
|
5292
|
+
if (activeIndex >= 0) commit(options[activeIndex]);
|
|
5293
|
+
} else if (e.key === "Escape" || e.key === "Tab") {
|
|
5294
|
+
setOpen(false);
|
|
5295
|
+
triggerRef.current?.focus();
|
|
5296
|
+
}
|
|
5297
|
+
},
|
|
5298
|
+
children: options.map((opt, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5299
|
+
"div",
|
|
5300
|
+
{
|
|
5301
|
+
role: "option",
|
|
5302
|
+
"aria-selected": opt.const === value,
|
|
5303
|
+
className: cn(
|
|
5304
|
+
"payman-v2-ua-select-option",
|
|
5305
|
+
i === activeIndex && "payman-v2-ua-select-option-active",
|
|
5306
|
+
opt.const === value && "payman-v2-ua-select-option-selected"
|
|
5307
|
+
),
|
|
5308
|
+
onMouseEnter: () => setActiveIndex(i),
|
|
5309
|
+
onClick: () => commit(opt),
|
|
5310
|
+
children: [
|
|
5311
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: opt.title || opt.const }),
|
|
5312
|
+
opt.const === value && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 13, "aria-hidden": true })
|
|
5313
|
+
]
|
|
5314
|
+
},
|
|
5315
|
+
opt.const
|
|
5316
|
+
))
|
|
5317
|
+
}
|
|
5318
|
+
),
|
|
5319
|
+
document.body
|
|
5320
|
+
)
|
|
5321
|
+
] });
|
|
5322
|
+
}
|
|
4673
5323
|
function SchemaFormInline({
|
|
4674
5324
|
prompt,
|
|
4675
5325
|
secondsLeft,
|
|
@@ -4715,7 +5365,7 @@ function SchemaFormInline({
|
|
|
4715
5365
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4716
5366
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "payman-v2-ua-icon", size: 14, strokeWidth: 1.75, "aria-hidden": true }),
|
|
4717
5367
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-title", children: "Action required" }),
|
|
4718
|
-
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" :
|
|
5368
|
+
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : /* @__PURE__ */ jsxRuntime.jsx(AnimatedDuration, { seconds: secondsLeft }) })
|
|
4719
5369
|
] }),
|
|
4720
5370
|
prompt.message?.trim() && (renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRendererV2, { content: prompt.message }) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: prompt.message })),
|
|
4721
5371
|
stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : fields.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-form", children: fields.map(([key, field]) => {
|
|
@@ -4747,26 +5397,33 @@ function SchemaFormInline({
|
|
|
4747
5397
|
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-req", children: "*" })
|
|
4748
5398
|
] }),
|
|
4749
5399
|
field.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-hint", children: field.description }),
|
|
4750
|
-
widget === "select" ? /* @__PURE__ */ jsxRuntime.
|
|
4751
|
-
|
|
5400
|
+
widget === "select" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5401
|
+
SelectFieldV2,
|
|
4752
5402
|
{
|
|
4753
5403
|
id: fieldId,
|
|
4754
|
-
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4755
5404
|
value: String(values[key] ?? ""),
|
|
5405
|
+
options: getOptions(field),
|
|
4756
5406
|
disabled: locked,
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
5407
|
+
error: Boolean(err),
|
|
5408
|
+
onChange: (v) => setValue(key, v)
|
|
5409
|
+
}
|
|
5410
|
+
) : widget === "decimal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5411
|
+
AmountFieldV2,
|
|
5412
|
+
{
|
|
5413
|
+
id: fieldId,
|
|
5414
|
+
value: String(values[key] ?? ""),
|
|
5415
|
+
disabled: locked,
|
|
5416
|
+
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
5417
|
+
onChange: (v) => setValue(key, v),
|
|
5418
|
+
onEnter: handleSubmit
|
|
4762
5419
|
}
|
|
4763
5420
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4764
5421
|
"input",
|
|
4765
5422
|
{
|
|
4766
5423
|
id: fieldId,
|
|
4767
|
-
type: widget === "integer"
|
|
4768
|
-
inputMode: widget === "integer" ? "numeric" :
|
|
4769
|
-
step: widget === "
|
|
5424
|
+
type: widget === "integer" ? "number" : "text",
|
|
5425
|
+
inputMode: widget === "integer" ? "numeric" : void 0,
|
|
5426
|
+
step: widget === "integer" ? "1" : void 0,
|
|
4770
5427
|
className: cn("payman-v2-ua-input", err && "payman-v2-ua-input-error"),
|
|
4771
5428
|
value: String(values[key] ?? ""),
|
|
4772
5429
|
disabled: locked,
|
|
@@ -4863,12 +5520,16 @@ function UserActionInline({
|
|
|
4863
5520
|
onSubmit,
|
|
4864
5521
|
onCancel,
|
|
4865
5522
|
onResend,
|
|
4866
|
-
onExpired
|
|
5523
|
+
onExpired,
|
|
5524
|
+
suppressExpiredNote
|
|
4867
5525
|
}) {
|
|
4868
5526
|
const [secondsLeft, expired] = useExpiryCountdown(prompt);
|
|
4869
5527
|
React.useEffect(() => {
|
|
4870
5528
|
if (expired && prompt.kind !== "notification") onExpired?.();
|
|
4871
5529
|
}, [expired, onExpired, prompt.kind]);
|
|
5530
|
+
if (expired && prompt.kind !== "notification" && suppressExpiredNote) {
|
|
5531
|
+
return null;
|
|
5532
|
+
}
|
|
4872
5533
|
let body;
|
|
4873
5534
|
if (expired && prompt.kind !== "notification") {
|
|
4874
5535
|
const note = {
|
|
@@ -4929,6 +5590,9 @@ function getPromptViewKey(prompt) {
|
|
|
4929
5590
|
prompt.message ?? ""
|
|
4930
5591
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4931
5592
|
}
|
|
5593
|
+
function getPromptMountKey(prompt) {
|
|
5594
|
+
return [getPromptSlotKey(prompt), prompt.userActionId].join(PROMPT_KEY_SEPARATOR);
|
|
5595
|
+
}
|
|
4932
5596
|
var MessageListV2 = React.forwardRef(
|
|
4933
5597
|
function MessageListV22({
|
|
4934
5598
|
messages,
|
|
@@ -4940,6 +5604,7 @@ var MessageListV2 = React.forwardRef(
|
|
|
4940
5604
|
messageActions,
|
|
4941
5605
|
retryDisabled = false,
|
|
4942
5606
|
userActionPrompts,
|
|
5607
|
+
dockedUserActionId,
|
|
4943
5608
|
notifications,
|
|
4944
5609
|
onSubmitUserAction,
|
|
4945
5610
|
onCancelUserAction,
|
|
@@ -5048,10 +5713,11 @@ var MessageListV2 = React.forwardRef(
|
|
|
5048
5713
|
}, [userActionPrompts]);
|
|
5049
5714
|
const visibleUserActionPrompts = React.useMemo(
|
|
5050
5715
|
() => userActionPrompts?.filter((prompt) => {
|
|
5716
|
+
if (prompt.userActionId === dockedUserActionId) return false;
|
|
5051
5717
|
const promptKey = getPromptViewKey(prompt);
|
|
5052
5718
|
return !expiredPromptViewState[promptKey]?.hidden;
|
|
5053
5719
|
}),
|
|
5054
|
-
[expiredPromptViewState, userActionPrompts]
|
|
5720
|
+
[dockedUserActionId, expiredPromptViewState, userActionPrompts]
|
|
5055
5721
|
);
|
|
5056
5722
|
const pinToBottom = React.useCallback((behavior = "instant") => {
|
|
5057
5723
|
const el = scrollRef.current;
|
|
@@ -5200,7 +5866,7 @@ var MessageListV2 = React.forwardRef(
|
|
|
5200
5866
|
onResend: onResendUserAction ?? noop,
|
|
5201
5867
|
onExpired: () => handleUserActionExpired(promptKey, prompt.userActionId)
|
|
5202
5868
|
},
|
|
5203
|
-
|
|
5869
|
+
getPromptMountKey(prompt)
|
|
5204
5870
|
);
|
|
5205
5871
|
})
|
|
5206
5872
|
]
|
|
@@ -5232,6 +5898,62 @@ var MessageListV2 = React.forwardRef(
|
|
|
5232
5898
|
] });
|
|
5233
5899
|
}
|
|
5234
5900
|
);
|
|
5901
|
+
function IconNewChat({ size = 16, className, style }) {
|
|
5902
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5903
|
+
"path",
|
|
5904
|
+
{
|
|
5905
|
+
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",
|
|
5906
|
+
stroke: "currentColor",
|
|
5907
|
+
strokeWidth: 2,
|
|
5908
|
+
strokeLinecap: "round",
|
|
5909
|
+
strokeLinejoin: "round"
|
|
5910
|
+
}
|
|
5911
|
+
) });
|
|
5912
|
+
}
|
|
5913
|
+
function IconPlus({ size = 16, className, style }) {
|
|
5914
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5915
|
+
"path",
|
|
5916
|
+
{
|
|
5917
|
+
d: "M12.0001 4.7998L12 19.1998M19.2 11.9998L4.80005 11.9998",
|
|
5918
|
+
stroke: "currentColor",
|
|
5919
|
+
strokeWidth: 2,
|
|
5920
|
+
strokeLinecap: "round"
|
|
5921
|
+
}
|
|
5922
|
+
) });
|
|
5923
|
+
}
|
|
5924
|
+
function IconMic({ size = 18, className, style }) {
|
|
5925
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5926
|
+
"path",
|
|
5927
|
+
{
|
|
5928
|
+
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",
|
|
5929
|
+
stroke: "currentColor",
|
|
5930
|
+
strokeWidth: 2,
|
|
5931
|
+
strokeLinecap: "round",
|
|
5932
|
+
strokeLinejoin: "round"
|
|
5933
|
+
}
|
|
5934
|
+
) });
|
|
5935
|
+
}
|
|
5936
|
+
function IconClock({ size = 12, className, style }) {
|
|
5937
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 25 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5938
|
+
"path",
|
|
5939
|
+
{
|
|
5940
|
+
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",
|
|
5941
|
+
fill: "currentColor"
|
|
5942
|
+
}
|
|
5943
|
+
) });
|
|
5944
|
+
}
|
|
5945
|
+
function IconMessage({ size = 12, className, style }) {
|
|
5946
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className, style, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5947
|
+
"path",
|
|
5948
|
+
{
|
|
5949
|
+
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",
|
|
5950
|
+
stroke: "currentColor",
|
|
5951
|
+
strokeWidth: 2,
|
|
5952
|
+
strokeLinecap: "round",
|
|
5953
|
+
strokeLinejoin: "round"
|
|
5954
|
+
}
|
|
5955
|
+
) });
|
|
5956
|
+
}
|
|
5235
5957
|
var ChatInputV2 = React.forwardRef(
|
|
5236
5958
|
function ChatInputV22({
|
|
5237
5959
|
onSend,
|
|
@@ -5622,12 +6344,7 @@ var ChatInputV2 = React.forwardRef(
|
|
|
5622
6344
|
showActions && "payman-v2-input-attach-btn-active"
|
|
5623
6345
|
),
|
|
5624
6346
|
"aria-label": "Attach",
|
|
5625
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5626
|
-
lucideReact.Plus,
|
|
5627
|
-
{
|
|
5628
|
-
style: { width: 20, height: 20, strokeWidth: 2 }
|
|
5629
|
-
}
|
|
5630
|
-
)
|
|
6347
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(IconPlus, { size: 20 })
|
|
5631
6348
|
}
|
|
5632
6349
|
),
|
|
5633
6350
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showActions && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -5710,7 +6427,7 @@ var ChatInputV2 = React.forwardRef(
|
|
|
5710
6427
|
),
|
|
5711
6428
|
"aria-label": isRecording ? "Stop recording" : "Voice input",
|
|
5712
6429
|
children: [
|
|
5713
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6430
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconMic, { size: 18 }),
|
|
5714
6431
|
isRecording && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-input-mic-indicator" })
|
|
5715
6432
|
]
|
|
5716
6433
|
}
|
|
@@ -5746,67 +6463,578 @@ var ChatInputV2 = React.forwardRef(
|
|
|
5746
6463
|
] });
|
|
5747
6464
|
}
|
|
5748
6465
|
);
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
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=";
|
|
5752
|
-
var DEFAULT_SIZE = 36;
|
|
5753
|
-
function useElapsedSeconds(isStreaming) {
|
|
5754
|
-
const [elapsed, setElapsed] = React.useState(0);
|
|
5755
|
-
const startRef = React.useRef(null);
|
|
5756
|
-
React.useEffect(() => {
|
|
5757
|
-
if (!isStreaming) {
|
|
5758
|
-
startRef.current = null;
|
|
5759
|
-
setElapsed(0);
|
|
5760
|
-
return;
|
|
5761
|
-
}
|
|
5762
|
-
startRef.current = performance.now();
|
|
5763
|
-
setElapsed(0);
|
|
5764
|
-
const id = setInterval(() => {
|
|
5765
|
-
if (startRef.current == null) return;
|
|
5766
|
-
const secs = Math.floor((performance.now() - startRef.current) / 1e3);
|
|
5767
|
-
setElapsed(secs);
|
|
5768
|
-
}, 100);
|
|
5769
|
-
return () => clearInterval(id);
|
|
5770
|
-
}, [isStreaming]);
|
|
5771
|
-
return elapsed;
|
|
6466
|
+
function dockKey(prompt) {
|
|
6467
|
+
return `${prompt.toolCallId || prompt.userActionId}:${prompt.userActionId}`;
|
|
5772
6468
|
}
|
|
5773
|
-
function
|
|
5774
|
-
|
|
5775
|
-
|
|
6469
|
+
function UserActionDock({
|
|
6470
|
+
prompt,
|
|
6471
|
+
onSubmit,
|
|
6472
|
+
onCancel,
|
|
6473
|
+
onResend,
|
|
6474
|
+
onExpired,
|
|
6475
|
+
children
|
|
5776
6476
|
}) {
|
|
5777
|
-
|
|
5778
|
-
const elapsed = useElapsedSeconds(isStreaming);
|
|
5779
|
-
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isStreaming && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6477
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-dock", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.motion.div, { layout: "size", transition: { duration: 0.3, ease: [0.2, 0, 0, 1] }, children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", initial: false, children: prompt ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5780
6478
|
framerMotion.motion.div,
|
|
5781
6479
|
{
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
6480
|
+
initial: { opacity: 0 },
|
|
6481
|
+
animate: { opacity: 1 },
|
|
6482
|
+
exit: { opacity: 0 },
|
|
6483
|
+
transition: { duration: 0.15 },
|
|
6484
|
+
className: "payman-v2-ua-dock-panel",
|
|
6485
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6486
|
+
UserActionInline,
|
|
6487
|
+
{
|
|
6488
|
+
prompt,
|
|
6489
|
+
onSubmit,
|
|
6490
|
+
onCancel,
|
|
6491
|
+
onResend,
|
|
6492
|
+
onExpired: () => onExpired?.(prompt.userActionId),
|
|
6493
|
+
suppressExpiredNote: true
|
|
6494
|
+
}
|
|
6495
|
+
)
|
|
6496
|
+
},
|
|
6497
|
+
dockKey(prompt)
|
|
6498
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6499
|
+
framerMotion.motion.div,
|
|
6500
|
+
{
|
|
6501
|
+
initial: { opacity: 0 },
|
|
6502
|
+
animate: { opacity: 1 },
|
|
6503
|
+
exit: { opacity: 0 },
|
|
6504
|
+
transition: { duration: 0.15 },
|
|
6505
|
+
children
|
|
6506
|
+
},
|
|
6507
|
+
"composer"
|
|
6508
|
+
) }) }) });
|
|
6509
|
+
}
|
|
6510
|
+
function clamp(value) {
|
|
6511
|
+
return Math.max(0, Math.min(1, value));
|
|
6512
|
+
}
|
|
6513
|
+
function ensureFrameSize(frame, rows, cols) {
|
|
6514
|
+
const result = [];
|
|
6515
|
+
for (let r = 0; r < rows; r++) {
|
|
6516
|
+
const row = frame[r] || [];
|
|
6517
|
+
result.push([]);
|
|
6518
|
+
for (let c = 0; c < cols; c++) {
|
|
6519
|
+
result[r][c] = row[c] ?? 0;
|
|
6520
|
+
}
|
|
6521
|
+
}
|
|
6522
|
+
return result;
|
|
6523
|
+
}
|
|
6524
|
+
function useAnimation(frames, options) {
|
|
6525
|
+
const [frameIndex, setFrameIndex] = React.useState(0);
|
|
6526
|
+
const [isPlaying, setIsPlaying] = React.useState(options.autoplay);
|
|
6527
|
+
const frameIdRef = React.useRef(void 0);
|
|
6528
|
+
const lastTimeRef = React.useRef(0);
|
|
6529
|
+
const accumulatorRef = React.useRef(0);
|
|
6530
|
+
React.useEffect(() => {
|
|
6531
|
+
if (!frames || frames.length === 0 || !isPlaying) {
|
|
6532
|
+
return;
|
|
6533
|
+
}
|
|
6534
|
+
const frameInterval = 1e3 / options.fps;
|
|
6535
|
+
const animate = (currentTime) => {
|
|
6536
|
+
if (lastTimeRef.current === 0) {
|
|
6537
|
+
lastTimeRef.current = currentTime;
|
|
6538
|
+
}
|
|
6539
|
+
const deltaTime = currentTime - lastTimeRef.current;
|
|
6540
|
+
lastTimeRef.current = currentTime;
|
|
6541
|
+
accumulatorRef.current += deltaTime;
|
|
6542
|
+
if (accumulatorRef.current >= frameInterval) {
|
|
6543
|
+
accumulatorRef.current -= frameInterval;
|
|
6544
|
+
setFrameIndex((prev) => {
|
|
6545
|
+
const next = prev + 1;
|
|
6546
|
+
if (next >= frames.length) {
|
|
6547
|
+
if (options.loop) {
|
|
6548
|
+
options.onFrame?.(0);
|
|
6549
|
+
return 0;
|
|
6550
|
+
} else {
|
|
6551
|
+
setIsPlaying(false);
|
|
6552
|
+
return prev;
|
|
6553
|
+
}
|
|
6554
|
+
}
|
|
6555
|
+
options.onFrame?.(next);
|
|
6556
|
+
return next;
|
|
6557
|
+
});
|
|
6558
|
+
}
|
|
6559
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6560
|
+
};
|
|
6561
|
+
frameIdRef.current = requestAnimationFrame(animate);
|
|
6562
|
+
return () => {
|
|
6563
|
+
if (frameIdRef.current) {
|
|
6564
|
+
cancelAnimationFrame(frameIdRef.current);
|
|
6565
|
+
}
|
|
6566
|
+
};
|
|
6567
|
+
}, [frames, isPlaying, options.fps, options.loop, options.onFrame]);
|
|
6568
|
+
React.useEffect(() => {
|
|
6569
|
+
setFrameIndex(0);
|
|
6570
|
+
setIsPlaying(options.autoplay);
|
|
6571
|
+
lastTimeRef.current = 0;
|
|
6572
|
+
accumulatorRef.current = 0;
|
|
6573
|
+
}, [frames, options.autoplay]);
|
|
6574
|
+
return { frameIndex, isPlaying };
|
|
6575
|
+
}
|
|
6576
|
+
function emptyFrame(rows, cols) {
|
|
6577
|
+
return Array.from({ length: rows }, () => Array(cols).fill(0));
|
|
6578
|
+
}
|
|
6579
|
+
function setPixel(frame, row, col, value) {
|
|
6580
|
+
if (row >= 0 && row < frame.length && col >= 0 && col < frame[0].length) {
|
|
6581
|
+
frame[row][col] = value;
|
|
6582
|
+
}
|
|
6583
|
+
}
|
|
6584
|
+
var loader = (() => {
|
|
6585
|
+
const frames = [];
|
|
6586
|
+
const size = 7;
|
|
6587
|
+
const center = 3;
|
|
6588
|
+
const radius = 2.5;
|
|
6589
|
+
for (let frame = 0; frame < 12; frame++) {
|
|
6590
|
+
const f = emptyFrame(size, size);
|
|
6591
|
+
for (let i = 0; i < 8; i++) {
|
|
6592
|
+
const angle = frame / 12 * Math.PI * 2 + i / 8 * Math.PI * 2;
|
|
6593
|
+
const x = Math.round(center + Math.cos(angle) * radius);
|
|
6594
|
+
const y = Math.round(center + Math.sin(angle) * radius);
|
|
6595
|
+
const brightness = 1 - i / 10;
|
|
6596
|
+
setPixel(f, y, x, Math.max(0.2, brightness));
|
|
6597
|
+
}
|
|
6598
|
+
frames.push(f);
|
|
6599
|
+
}
|
|
6600
|
+
return frames;
|
|
6601
|
+
})();
|
|
6602
|
+
var pulse = (() => {
|
|
6603
|
+
const frames = [];
|
|
6604
|
+
const size = 7;
|
|
6605
|
+
const center = 3;
|
|
6606
|
+
for (let frame = 0; frame < 16; frame++) {
|
|
6607
|
+
const f = emptyFrame(size, size);
|
|
6608
|
+
const phase = frame / 16 * Math.PI * 2;
|
|
6609
|
+
const intensity = (Math.sin(phase) + 1) / 2;
|
|
6610
|
+
setPixel(f, center, center, 1);
|
|
6611
|
+
const radius = Math.floor((1 - intensity) * 3) + 1;
|
|
6612
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
6613
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
6614
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
6615
|
+
if (Math.abs(dist - radius) < 0.7) {
|
|
6616
|
+
setPixel(f, center + dy, center + dx, intensity * 0.6);
|
|
6617
|
+
}
|
|
6618
|
+
}
|
|
6619
|
+
}
|
|
6620
|
+
frames.push(f);
|
|
6621
|
+
}
|
|
6622
|
+
return frames;
|
|
6623
|
+
})();
|
|
6624
|
+
function vu(columns, levels) {
|
|
6625
|
+
const rows = 7;
|
|
6626
|
+
const frame = emptyFrame(rows, columns);
|
|
6627
|
+
for (let col = 0; col < Math.min(columns, levels.length); col++) {
|
|
6628
|
+
const level = Math.max(0, Math.min(1, levels[col]));
|
|
6629
|
+
const height = Math.floor(level * rows);
|
|
6630
|
+
for (let row = 0; row < rows; row++) {
|
|
6631
|
+
const rowFromBottom = rows - 1 - row;
|
|
6632
|
+
if (rowFromBottom < height) {
|
|
6633
|
+
let brightness = 1;
|
|
6634
|
+
if (row < rows * 0.3) {
|
|
6635
|
+
brightness = 1;
|
|
6636
|
+
} else if (row < rows * 0.6) {
|
|
6637
|
+
brightness = 0.8;
|
|
6638
|
+
} else {
|
|
6639
|
+
brightness = 0.6;
|
|
6640
|
+
}
|
|
6641
|
+
frame[row][col] = brightness;
|
|
6642
|
+
}
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
return frame;
|
|
6646
|
+
}
|
|
6647
|
+
var wave = (() => {
|
|
6648
|
+
const frames = [];
|
|
6649
|
+
const rows = 7;
|
|
6650
|
+
const cols = 7;
|
|
6651
|
+
for (let frame = 0; frame < 24; frame++) {
|
|
6652
|
+
const f = emptyFrame(rows, cols);
|
|
6653
|
+
const phase = frame / 24 * Math.PI * 2;
|
|
6654
|
+
for (let col = 0; col < cols; col++) {
|
|
6655
|
+
const colPhase = col / cols * Math.PI * 2;
|
|
6656
|
+
const height = Math.sin(phase + colPhase) * 2.5 + 3.5;
|
|
6657
|
+
const row = Math.floor(height);
|
|
6658
|
+
if (row >= 0 && row < rows) {
|
|
6659
|
+
setPixel(f, row, col, 1);
|
|
6660
|
+
const frac = height - row;
|
|
6661
|
+
if (row > 0) setPixel(f, row - 1, col, 1 - frac);
|
|
6662
|
+
if (row < rows - 1) setPixel(f, row + 1, col, frac);
|
|
6663
|
+
}
|
|
6664
|
+
}
|
|
6665
|
+
frames.push(f);
|
|
6666
|
+
}
|
|
6667
|
+
return frames;
|
|
6668
|
+
})();
|
|
6669
|
+
var snake = (() => {
|
|
6670
|
+
const frames = [];
|
|
6671
|
+
const rows = 7;
|
|
6672
|
+
const cols = 7;
|
|
6673
|
+
const path = [];
|
|
6674
|
+
let x = 0;
|
|
6675
|
+
let y = 0;
|
|
6676
|
+
let dx = 1;
|
|
6677
|
+
let dy = 0;
|
|
6678
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6679
|
+
while (path.length < rows * cols) {
|
|
6680
|
+
path.push([y, x]);
|
|
6681
|
+
visited.add(`${y},${x}`);
|
|
6682
|
+
const nextX = x + dx;
|
|
6683
|
+
const nextY = y + dy;
|
|
6684
|
+
if (nextX >= 0 && nextX < cols && nextY >= 0 && nextY < rows && !visited.has(`${nextY},${nextX}`)) {
|
|
6685
|
+
x = nextX;
|
|
6686
|
+
y = nextY;
|
|
6687
|
+
} else {
|
|
6688
|
+
const newDx = -dy;
|
|
6689
|
+
const newDy = dx;
|
|
6690
|
+
dx = newDx;
|
|
6691
|
+
dy = newDy;
|
|
6692
|
+
const nextX2 = x + dx;
|
|
6693
|
+
const nextY2 = y + dy;
|
|
6694
|
+
if (nextX2 >= 0 && nextX2 < cols && nextY2 >= 0 && nextY2 < rows && !visited.has(`${nextY2},${nextX2}`)) {
|
|
6695
|
+
x = nextX2;
|
|
6696
|
+
y = nextY2;
|
|
6697
|
+
} else {
|
|
6698
|
+
break;
|
|
6699
|
+
}
|
|
6700
|
+
}
|
|
6701
|
+
}
|
|
6702
|
+
const snakeLength = 5;
|
|
6703
|
+
for (let frame = 0; frame < path.length; frame++) {
|
|
6704
|
+
const f = emptyFrame(rows, cols);
|
|
6705
|
+
for (let i = 0; i < snakeLength; i++) {
|
|
6706
|
+
const idx = frame - i;
|
|
6707
|
+
if (idx >= 0 && idx < path.length) {
|
|
6708
|
+
const [y2, x2] = path[idx];
|
|
6709
|
+
const brightness = 1 - i / snakeLength;
|
|
6710
|
+
setPixel(f, y2, x2, brightness);
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
frames.push(f);
|
|
6714
|
+
}
|
|
6715
|
+
return frames;
|
|
6716
|
+
})();
|
|
6717
|
+
var Matrix = React__namespace.forwardRef(
|
|
6718
|
+
({
|
|
6719
|
+
rows,
|
|
6720
|
+
cols,
|
|
6721
|
+
pattern,
|
|
6722
|
+
frames,
|
|
6723
|
+
fps = 12,
|
|
6724
|
+
autoplay = true,
|
|
6725
|
+
loop = true,
|
|
6726
|
+
size = 10,
|
|
6727
|
+
gap = 2,
|
|
6728
|
+
palette = {
|
|
6729
|
+
on: "currentColor",
|
|
6730
|
+
off: "var(--muted-foreground)"
|
|
6731
|
+
},
|
|
6732
|
+
brightness = 1,
|
|
6733
|
+
ariaLabel,
|
|
6734
|
+
onFrame,
|
|
6735
|
+
mode = "default",
|
|
6736
|
+
levels,
|
|
6737
|
+
className,
|
|
6738
|
+
...props
|
|
6739
|
+
}, ref) => {
|
|
6740
|
+
const { frameIndex } = useAnimation(frames, {
|
|
6741
|
+
fps,
|
|
6742
|
+
autoplay: autoplay && !pattern,
|
|
6743
|
+
loop,
|
|
6744
|
+
onFrame
|
|
6745
|
+
});
|
|
6746
|
+
const currentFrame = React.useMemo(() => {
|
|
6747
|
+
if (mode === "vu" && levels && levels.length > 0) {
|
|
6748
|
+
return ensureFrameSize(vu(cols, levels), rows, cols);
|
|
6749
|
+
}
|
|
6750
|
+
if (pattern) {
|
|
6751
|
+
return ensureFrameSize(pattern, rows, cols);
|
|
6752
|
+
}
|
|
6753
|
+
if (frames && frames.length > 0) {
|
|
6754
|
+
return ensureFrameSize(frames[frameIndex] || frames[0], rows, cols);
|
|
6755
|
+
}
|
|
6756
|
+
return ensureFrameSize([], rows, cols);
|
|
6757
|
+
}, [pattern, frames, frameIndex, rows, cols, mode, levels]);
|
|
6758
|
+
const cellPositions = React.useMemo(() => {
|
|
6759
|
+
const positions = [];
|
|
6760
|
+
for (let row = 0; row < rows; row++) {
|
|
6761
|
+
positions[row] = [];
|
|
6762
|
+
for (let col = 0; col < cols; col++) {
|
|
6763
|
+
positions[row][col] = {
|
|
6764
|
+
x: col * (size + gap),
|
|
6765
|
+
y: row * (size + gap)
|
|
6766
|
+
};
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
return positions;
|
|
6770
|
+
}, [rows, cols, size, gap]);
|
|
6771
|
+
const svgDimensions = React.useMemo(() => {
|
|
6772
|
+
return {
|
|
6773
|
+
width: cols * (size + gap) - gap,
|
|
6774
|
+
height: rows * (size + gap) - gap
|
|
6775
|
+
};
|
|
6776
|
+
}, [rows, cols, size, gap]);
|
|
6777
|
+
const isAnimating = !pattern && frames && frames.length > 0;
|
|
6778
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6779
|
+
"div",
|
|
6780
|
+
{
|
|
6781
|
+
ref,
|
|
6782
|
+
role: "img",
|
|
6783
|
+
"aria-label": ariaLabel ?? "matrix display",
|
|
6784
|
+
"aria-live": isAnimating ? "polite" : void 0,
|
|
6785
|
+
className: cn("relative inline-block", className),
|
|
6786
|
+
style: {
|
|
6787
|
+
"--matrix-on": palette.on,
|
|
6788
|
+
"--matrix-off": palette.off,
|
|
6789
|
+
"--matrix-gap": `${gap}px`,
|
|
6790
|
+
"--matrix-size": `${size}px`
|
|
6791
|
+
},
|
|
6792
|
+
...props,
|
|
6793
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6794
|
+
"svg",
|
|
6795
|
+
{
|
|
6796
|
+
width: svgDimensions.width,
|
|
6797
|
+
height: svgDimensions.height,
|
|
6798
|
+
viewBox: `0 0 ${svgDimensions.width} ${svgDimensions.height}`,
|
|
6799
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6800
|
+
className: "block",
|
|
6801
|
+
style: { overflow: "visible" },
|
|
6802
|
+
children: [
|
|
6803
|
+
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
6804
|
+
/* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: "matrix-pixel-on", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6805
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "var(--matrix-on)", stopOpacity: "1" }),
|
|
6806
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6807
|
+
"stop",
|
|
6808
|
+
{
|
|
6809
|
+
offset: "70%",
|
|
6810
|
+
stopColor: "var(--matrix-on)",
|
|
6811
|
+
stopOpacity: "0.85"
|
|
6812
|
+
}
|
|
6813
|
+
),
|
|
6814
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6815
|
+
"stop",
|
|
6816
|
+
{
|
|
6817
|
+
offset: "100%",
|
|
6818
|
+
stopColor: "var(--matrix-on)",
|
|
6819
|
+
stopOpacity: "0.6"
|
|
6820
|
+
}
|
|
6821
|
+
)
|
|
6822
|
+
] }),
|
|
6823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: "matrix-pixel-off", cx: "50%", cy: "50%", r: "50%", children: [
|
|
6824
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6825
|
+
"stop",
|
|
6826
|
+
{
|
|
6827
|
+
offset: "0%",
|
|
6828
|
+
stopColor: "var(--muted-foreground)",
|
|
6829
|
+
stopOpacity: "1"
|
|
6830
|
+
}
|
|
6831
|
+
),
|
|
6832
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6833
|
+
"stop",
|
|
6834
|
+
{
|
|
6835
|
+
offset: "100%",
|
|
6836
|
+
stopColor: "var(--muted-foreground)",
|
|
6837
|
+
stopOpacity: "0.7"
|
|
6838
|
+
}
|
|
6839
|
+
)
|
|
6840
|
+
] }),
|
|
6841
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6842
|
+
"filter",
|
|
6843
|
+
{
|
|
6844
|
+
id: "matrix-glow",
|
|
6845
|
+
x: "-50%",
|
|
6846
|
+
y: "-50%",
|
|
6847
|
+
width: "200%",
|
|
6848
|
+
height: "200%",
|
|
6849
|
+
children: [
|
|
6850
|
+
/* @__PURE__ */ jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "2", result: "blur" }),
|
|
6851
|
+
/* @__PURE__ */ jsxRuntime.jsx("feComposite", { in: "SourceGraphic", in2: "blur", operator: "over" })
|
|
6852
|
+
]
|
|
6853
|
+
}
|
|
6854
|
+
)
|
|
6855
|
+
] }),
|
|
6856
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
6857
|
+
.matrix-pixel {
|
|
6858
|
+
transition: opacity 300ms ease-out, transform 150ms ease-out;
|
|
6859
|
+
transform-origin: center;
|
|
6860
|
+
transform-box: fill-box;
|
|
6861
|
+
}
|
|
6862
|
+
.matrix-pixel-active {
|
|
6863
|
+
filter: url(#matrix-glow);
|
|
6864
|
+
}
|
|
6865
|
+
` }),
|
|
6866
|
+
currentFrame.map(
|
|
6867
|
+
(row, rowIndex) => row.map((value, colIndex) => {
|
|
6868
|
+
const pos = cellPositions[rowIndex]?.[colIndex];
|
|
6869
|
+
if (!pos) return null;
|
|
6870
|
+
const opacity = clamp(brightness * value);
|
|
6871
|
+
const isActive = opacity > 0.5;
|
|
6872
|
+
const isOn = opacity > 0.05;
|
|
6873
|
+
const fill = isOn ? "url(#matrix-pixel-on)" : "url(#matrix-pixel-off)";
|
|
6874
|
+
const scale = isActive ? 1.1 : 1;
|
|
6875
|
+
const radius = size / 2 * 0.9;
|
|
6876
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6877
|
+
"circle",
|
|
6878
|
+
{
|
|
6879
|
+
className: cn(
|
|
6880
|
+
"matrix-pixel",
|
|
6881
|
+
isActive && "matrix-pixel-active",
|
|
6882
|
+
!isOn && "opacity-20 dark:opacity-[0.1]"
|
|
6883
|
+
),
|
|
6884
|
+
cx: pos.x + size / 2,
|
|
6885
|
+
cy: pos.y + size / 2,
|
|
6886
|
+
r: radius,
|
|
6887
|
+
fill,
|
|
6888
|
+
opacity: isOn ? opacity : 0.1,
|
|
6889
|
+
style: {
|
|
6890
|
+
transform: `scale(${scale})`
|
|
6891
|
+
}
|
|
6892
|
+
},
|
|
6893
|
+
`${rowIndex}-${colIndex}`
|
|
6894
|
+
);
|
|
6895
|
+
})
|
|
6896
|
+
)
|
|
6897
|
+
]
|
|
6898
|
+
}
|
|
6899
|
+
)
|
|
6900
|
+
}
|
|
6901
|
+
);
|
|
6902
|
+
}
|
|
6903
|
+
);
|
|
6904
|
+
Matrix.displayName = "Matrix";
|
|
6905
|
+
var DEFAULT_SIZE = 22;
|
|
6906
|
+
var MATRIX_GRID = 7;
|
|
6907
|
+
var MATRIX_ON = "var(--payman-v2-matrix-color)";
|
|
6908
|
+
var MATRIX_PRESETS = [
|
|
6909
|
+
{ frames: loader, fps: 8 },
|
|
6910
|
+
{ frames: wave, fps: 14 },
|
|
6911
|
+
{ frames: snake, fps: 16 },
|
|
6912
|
+
{ frames: pulse, fps: 12 }
|
|
6913
|
+
];
|
|
6914
|
+
var PRESET_ROTATE_MS = 1e4;
|
|
6915
|
+
function useElapsedSeconds(isStreaming) {
|
|
6916
|
+
const [elapsed, setElapsed] = React.useState(0);
|
|
6917
|
+
const startRef = React.useRef(null);
|
|
6918
|
+
React.useEffect(() => {
|
|
6919
|
+
if (!isStreaming) {
|
|
6920
|
+
startRef.current = null;
|
|
6921
|
+
setElapsed(0);
|
|
6922
|
+
return;
|
|
6923
|
+
}
|
|
6924
|
+
startRef.current = performance.now();
|
|
6925
|
+
setElapsed(0);
|
|
6926
|
+
const id = setInterval(() => {
|
|
6927
|
+
if (startRef.current == null) return;
|
|
6928
|
+
const secs = Math.floor((performance.now() - startRef.current) / 1e3);
|
|
6929
|
+
setElapsed(secs);
|
|
6930
|
+
}, 100);
|
|
6931
|
+
return () => clearInterval(id);
|
|
6932
|
+
}, [isStreaming]);
|
|
6933
|
+
return elapsed;
|
|
6934
|
+
}
|
|
6935
|
+
function useMatrixPresetIndex(isStreaming) {
|
|
6936
|
+
const [index, setIndex] = React.useState(0);
|
|
6937
|
+
React.useEffect(() => {
|
|
6938
|
+
if (!isStreaming) return;
|
|
6939
|
+
setIndex(0);
|
|
6940
|
+
const id = setInterval(() => {
|
|
6941
|
+
setIndex((prev) => (prev + 1) % MATRIX_PRESETS.length);
|
|
6942
|
+
}, PRESET_ROTATE_MS);
|
|
6943
|
+
return () => clearInterval(id);
|
|
6944
|
+
}, [isStreaming]);
|
|
6945
|
+
return index;
|
|
6946
|
+
}
|
|
6947
|
+
function formatElapsed(totalSeconds) {
|
|
6948
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
6949
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6950
|
+
const seconds = totalSeconds % 60;
|
|
6951
|
+
return `${minutes}m ${seconds}s`;
|
|
6952
|
+
}
|
|
6953
|
+
function StreamingIndicatorV2({
|
|
6954
|
+
isStreaming,
|
|
6955
|
+
loadingAnimation
|
|
6956
|
+
}) {
|
|
6957
|
+
const size = loadingAnimation?.size ?? DEFAULT_SIZE;
|
|
6958
|
+
const elapsed = useElapsedSeconds(isStreaming);
|
|
6959
|
+
const presetIndex = useMatrixPresetIndex(isStreaming);
|
|
6960
|
+
const preset = MATRIX_PRESETS[presetIndex];
|
|
6961
|
+
const gap = 1;
|
|
6962
|
+
const cell = React.useMemo(
|
|
6963
|
+
() => Math.max(2, Math.round((size - (MATRIX_GRID - 1) * gap) / MATRIX_GRID)),
|
|
6964
|
+
[size]
|
|
6965
|
+
);
|
|
6966
|
+
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isStreaming && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6967
|
+
framerMotion.motion.div,
|
|
6968
|
+
{
|
|
6969
|
+
className: "payman-v2-streaming-indicator",
|
|
6970
|
+
initial: { opacity: 0, y: 4 },
|
|
6971
|
+
animate: { opacity: 1, y: 0 },
|
|
6972
|
+
exit: { opacity: 0, y: 4 },
|
|
6973
|
+
transition: { duration: 0.2 },
|
|
6974
|
+
"aria-hidden": "true",
|
|
6975
|
+
children: [
|
|
6976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6977
|
+
"div",
|
|
6978
|
+
{
|
|
6979
|
+
className: "payman-v2-streaming-indicator-glyph",
|
|
6980
|
+
style: { width: size, height: size },
|
|
6981
|
+
children: loadingAnimation?.src ? (
|
|
6982
|
+
// Consumer override: render their Lottie animation.
|
|
6983
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6984
|
+
dotlottieReact.DotLottieReact,
|
|
6985
|
+
{
|
|
6986
|
+
src: loadingAnimation.src,
|
|
6987
|
+
loop: true,
|
|
6988
|
+
autoplay: true,
|
|
6989
|
+
style: { width: "100%", height: "100%" }
|
|
6990
|
+
}
|
|
6991
|
+
)
|
|
6992
|
+
) : (
|
|
6993
|
+
// Default: dot-matrix glyph, cycling presets +
|
|
6994
|
+
// Payman brand tint. Each preset lives in its own
|
|
6995
|
+
// keyed motion layer so swapping presets crossfades
|
|
6996
|
+
// (old scales/fades out while the new scales/fades
|
|
6997
|
+
// in) instead of hard-cutting. Keying the layer on
|
|
6998
|
+
// `presetIndex` also remounts the Matrix, restarting
|
|
6999
|
+
// its frame counter cleanly at frame 0.
|
|
7000
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7001
|
+
framerMotion.motion.div,
|
|
7002
|
+
{
|
|
7003
|
+
className: "payman-v2-streaming-indicator-matrix",
|
|
7004
|
+
initial: { opacity: 0, scale: 0.8 },
|
|
7005
|
+
animate: { opacity: 1, scale: 1 },
|
|
7006
|
+
exit: { opacity: 0, scale: 0.8 },
|
|
7007
|
+
transition: { duration: 0.45, ease: [0.2, 0, 0, 1] },
|
|
7008
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7009
|
+
Matrix,
|
|
7010
|
+
{
|
|
7011
|
+
rows: MATRIX_GRID,
|
|
7012
|
+
cols: MATRIX_GRID,
|
|
7013
|
+
frames: preset.frames,
|
|
7014
|
+
fps: preset.fps,
|
|
7015
|
+
size: cell,
|
|
7016
|
+
gap,
|
|
7017
|
+
palette: {
|
|
7018
|
+
on: MATRIX_ON,
|
|
7019
|
+
// Unlit dots use the v2 theme's own muted-text
|
|
7020
|
+
// token (light/dark-aware), not the bare
|
|
7021
|
+
// `--muted-foreground` the vendored Matrix
|
|
7022
|
+
// component falls back to internally — that
|
|
7023
|
+
// variable isn't defined under `.payman-v2-root`
|
|
7024
|
+
// and would otherwise resolve to black.
|
|
7025
|
+
off: "var(--payman-v2-matrix-dot-off)"
|
|
7026
|
+
},
|
|
7027
|
+
ariaLabel: "Working\u2026"
|
|
7028
|
+
}
|
|
7029
|
+
)
|
|
7030
|
+
},
|
|
7031
|
+
presetIndex
|
|
7032
|
+
) })
|
|
7033
|
+
)
|
|
7034
|
+
}
|
|
7035
|
+
),
|
|
7036
|
+
elapsed > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-streaming-indicator-elapsed", children: formatElapsed(elapsed) })
|
|
7037
|
+
]
|
|
5810
7038
|
},
|
|
5811
7039
|
"streaming-indicator"
|
|
5812
7040
|
) });
|
|
@@ -6181,82 +7409,660 @@ function TimelineBars({
|
|
|
6181
7409
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6182
7410
|
"div",
|
|
6183
7411
|
{
|
|
6184
|
-
style: {
|
|
6185
|
-
height: "100%",
|
|
6186
|
-
width: `${Math.max(widthPct, 0.3)}%`,
|
|
6187
|
-
background: stepColor(step2),
|
|
6188
|
-
transition: "width 0.2s ease"
|
|
6189
|
-
}
|
|
7412
|
+
style: {
|
|
7413
|
+
height: "100%",
|
|
7414
|
+
width: `${Math.max(widthPct, 0.3)}%`,
|
|
7415
|
+
background: stepColor(step2),
|
|
7416
|
+
transition: "width 0.2s ease"
|
|
7417
|
+
}
|
|
7418
|
+
}
|
|
7419
|
+
)
|
|
7420
|
+
}
|
|
7421
|
+
)
|
|
7422
|
+
] }, `${step2.step}-${step2.startTime}`);
|
|
7423
|
+
});
|
|
7424
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7425
|
+
bars,
|
|
7426
|
+
unaccountedMs > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 8 }, children: [
|
|
7427
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7428
|
+
"div",
|
|
7429
|
+
{
|
|
7430
|
+
style: {
|
|
7431
|
+
display: "flex",
|
|
7432
|
+
justifyContent: "space-between",
|
|
7433
|
+
fontSize: 12,
|
|
7434
|
+
marginBottom: 4,
|
|
7435
|
+
fontFamily: "ui-monospace, SFMono-Regular, monospace",
|
|
7436
|
+
opacity: 0.7
|
|
7437
|
+
},
|
|
7438
|
+
children: [
|
|
7439
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "(unaccounted)" }),
|
|
7440
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatMs(unaccountedMs) })
|
|
7441
|
+
]
|
|
7442
|
+
}
|
|
7443
|
+
),
|
|
7444
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7445
|
+
"div",
|
|
7446
|
+
{
|
|
7447
|
+
style: {
|
|
7448
|
+
height: 8,
|
|
7449
|
+
background: "rgba(255,255,255,0.06)",
|
|
7450
|
+
borderRadius: 4,
|
|
7451
|
+
overflow: "hidden"
|
|
7452
|
+
},
|
|
7453
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7454
|
+
"div",
|
|
7455
|
+
{
|
|
7456
|
+
style: {
|
|
7457
|
+
height: "100%",
|
|
7458
|
+
width: `${unaccountedMs / Math.max(totalMs, 1) * 100}%`,
|
|
7459
|
+
background: "repeating-linear-gradient(45deg, rgba(255,255,255,0.18) 0 4px, transparent 4px 8px)"
|
|
7460
|
+
}
|
|
7461
|
+
}
|
|
7462
|
+
)
|
|
7463
|
+
}
|
|
7464
|
+
)
|
|
7465
|
+
] }),
|
|
7466
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7467
|
+
"div",
|
|
7468
|
+
{
|
|
7469
|
+
style: {
|
|
7470
|
+
marginTop: 14,
|
|
7471
|
+
paddingTop: 12,
|
|
7472
|
+
borderTop: "1px solid rgba(255,255,255,0.08)",
|
|
7473
|
+
fontSize: 12,
|
|
7474
|
+
display: "flex",
|
|
7475
|
+
justifyContent: "space-between",
|
|
7476
|
+
opacity: 0.85
|
|
7477
|
+
},
|
|
7478
|
+
children: [
|
|
7479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
7480
|
+
trace.pipelineSteps.length,
|
|
7481
|
+
" step",
|
|
7482
|
+
trace.pipelineSteps.length === 1 ? "" : "s"
|
|
7483
|
+
] }),
|
|
7484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontFamily: "ui-monospace, SFMono-Regular, monospace" }, children: [
|
|
7485
|
+
"total: ",
|
|
7486
|
+
formatMs(totalMs)
|
|
7487
|
+
] })
|
|
7488
|
+
]
|
|
7489
|
+
}
|
|
7490
|
+
)
|
|
7491
|
+
] });
|
|
7492
|
+
}
|
|
7493
|
+
var MIN_SIDEBAR_WIDTH = 240;
|
|
7494
|
+
var MAX_SIDEBAR_WIDTH = 520;
|
|
7495
|
+
var DEFAULT_SIDEBAR_WIDTH = 264;
|
|
7496
|
+
var WIDTH_STORAGE_KEY = "payman-v2-sessions-width";
|
|
7497
|
+
function readStoredWidth() {
|
|
7498
|
+
if (typeof window === "undefined") return DEFAULT_SIDEBAR_WIDTH;
|
|
7499
|
+
const raw = Number(window.localStorage?.getItem(WIDTH_STORAGE_KEY));
|
|
7500
|
+
if (Number.isFinite(raw) && raw >= MIN_SIDEBAR_WIDTH && raw <= MAX_SIDEBAR_WIDTH) return raw;
|
|
7501
|
+
return DEFAULT_SIDEBAR_WIDTH;
|
|
7502
|
+
}
|
|
7503
|
+
function formatRelativeTime(iso) {
|
|
7504
|
+
if (!iso) return "";
|
|
7505
|
+
const date = new Date(iso);
|
|
7506
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
7507
|
+
const diffSec = Math.round((Date.now() - date.getTime()) / 1e3);
|
|
7508
|
+
if (diffSec < 60) return "just now";
|
|
7509
|
+
const diffMin = Math.round(diffSec / 60);
|
|
7510
|
+
if (diffMin < 60) return `${diffMin} minute${diffMin === 1 ? "" : "s"} ago`;
|
|
7511
|
+
const diffHr = Math.round(diffMin / 60);
|
|
7512
|
+
if (diffHr < 24) return `${diffHr} hour${diffHr === 1 ? "" : "s"} ago`;
|
|
7513
|
+
const diffDay = Math.round(diffHr / 24);
|
|
7514
|
+
if (diffDay < 7) return `${diffDay} day${diffDay === 1 ? "" : "s"} ago`;
|
|
7515
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
7516
|
+
}
|
|
7517
|
+
function SessionsSidebarV2({
|
|
7518
|
+
open,
|
|
7519
|
+
onClose,
|
|
7520
|
+
title,
|
|
7521
|
+
newChatLabel,
|
|
7522
|
+
sessions,
|
|
7523
|
+
isLoading,
|
|
7524
|
+
error,
|
|
7525
|
+
onRetry,
|
|
7526
|
+
selectedSessionId,
|
|
7527
|
+
onSelectSession,
|
|
7528
|
+
onNewSession,
|
|
7529
|
+
actions,
|
|
7530
|
+
hasMore,
|
|
7531
|
+
isLoadingMore,
|
|
7532
|
+
onLoadMore
|
|
7533
|
+
}) {
|
|
7534
|
+
const [width, setWidth] = React.useState(readStoredWidth);
|
|
7535
|
+
const [isResizing, setIsResizing] = React.useState(false);
|
|
7536
|
+
const dragState = React.useRef(null);
|
|
7537
|
+
const onResizeMove = React.useCallback((event) => {
|
|
7538
|
+
if (!dragState.current) return;
|
|
7539
|
+
const delta = event.clientX - dragState.current.startX;
|
|
7540
|
+
const next = Math.min(
|
|
7541
|
+
MAX_SIDEBAR_WIDTH,
|
|
7542
|
+
Math.max(MIN_SIDEBAR_WIDTH, dragState.current.startWidth + delta)
|
|
7543
|
+
);
|
|
7544
|
+
setWidth(next);
|
|
7545
|
+
}, []);
|
|
7546
|
+
const onResizeEnd = React.useCallback(() => {
|
|
7547
|
+
dragState.current = null;
|
|
7548
|
+
setIsResizing(false);
|
|
7549
|
+
document.removeEventListener("mousemove", onResizeMove);
|
|
7550
|
+
document.removeEventListener("mouseup", onResizeEnd);
|
|
7551
|
+
document.body.style.removeProperty("user-select");
|
|
7552
|
+
setWidth((w) => {
|
|
7553
|
+
if (typeof window !== "undefined") window.localStorage?.setItem(WIDTH_STORAGE_KEY, String(w));
|
|
7554
|
+
return w;
|
|
7555
|
+
});
|
|
7556
|
+
}, [onResizeMove]);
|
|
7557
|
+
const onResizeStart = React.useCallback(
|
|
7558
|
+
(event) => {
|
|
7559
|
+
event.preventDefault();
|
|
7560
|
+
dragState.current = { startX: event.clientX, startWidth: width };
|
|
7561
|
+
setIsResizing(true);
|
|
7562
|
+
document.body.style.userSelect = "none";
|
|
7563
|
+
document.addEventListener("mousemove", onResizeMove);
|
|
7564
|
+
document.addEventListener("mouseup", onResizeEnd);
|
|
7565
|
+
},
|
|
7566
|
+
[width, onResizeMove, onResizeEnd]
|
|
7567
|
+
);
|
|
7568
|
+
React.useEffect(
|
|
7569
|
+
() => () => {
|
|
7570
|
+
document.removeEventListener("mousemove", onResizeMove);
|
|
7571
|
+
document.removeEventListener("mouseup", onResizeEnd);
|
|
7572
|
+
},
|
|
7573
|
+
[onResizeMove, onResizeEnd]
|
|
7574
|
+
);
|
|
7575
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7576
|
+
"div",
|
|
7577
|
+
{
|
|
7578
|
+
className: cn(
|
|
7579
|
+
"payman-v2-sessions-sidebar",
|
|
7580
|
+
!open && "payman-v2-sessions-sidebar-collapsed",
|
|
7581
|
+
isResizing && "payman-v2-sessions-sidebar-resizing"
|
|
7582
|
+
),
|
|
7583
|
+
role: "complementary",
|
|
7584
|
+
"aria-label": title,
|
|
7585
|
+
"aria-hidden": !open,
|
|
7586
|
+
style: { "--payman-v2-sessions-width": `${width}px` },
|
|
7587
|
+
children: [
|
|
7588
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-sidebar-inner", children: [
|
|
7589
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-header", children: [
|
|
7590
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-sessions-title", children: title }),
|
|
7591
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7592
|
+
"button",
|
|
7593
|
+
{
|
|
7594
|
+
type: "button",
|
|
7595
|
+
className: "payman-v2-sessions-close",
|
|
7596
|
+
onClick: onClose,
|
|
7597
|
+
"aria-label": "Close chats panel",
|
|
7598
|
+
tabIndex: open ? 0 : -1,
|
|
7599
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 })
|
|
7600
|
+
}
|
|
7601
|
+
)
|
|
7602
|
+
] }),
|
|
7603
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7604
|
+
"button",
|
|
7605
|
+
{
|
|
7606
|
+
type: "button",
|
|
7607
|
+
className: "payman-v2-sessions-new-btn",
|
|
7608
|
+
onClick: onNewSession,
|
|
7609
|
+
tabIndex: open ? 0 : -1,
|
|
7610
|
+
children: [
|
|
7611
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconNewChat, { size: 16 }),
|
|
7612
|
+
newChatLabel
|
|
7613
|
+
]
|
|
7614
|
+
}
|
|
7615
|
+
),
|
|
7616
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
7617
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7618
|
+
SessionsListBody,
|
|
7619
|
+
{
|
|
7620
|
+
sessions,
|
|
7621
|
+
isLoading,
|
|
7622
|
+
error,
|
|
7623
|
+
onRetry,
|
|
7624
|
+
selectedSessionId,
|
|
7625
|
+
onSelectSession,
|
|
7626
|
+
actions,
|
|
7627
|
+
hasMore,
|
|
7628
|
+
isLoadingMore,
|
|
7629
|
+
onLoadMore
|
|
7630
|
+
}
|
|
7631
|
+
)
|
|
7632
|
+
] }),
|
|
7633
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7634
|
+
"div",
|
|
7635
|
+
{
|
|
7636
|
+
className: "payman-v2-sessions-resizer",
|
|
7637
|
+
onMouseDown: onResizeStart,
|
|
7638
|
+
role: "separator",
|
|
7639
|
+
"aria-orientation": "vertical",
|
|
7640
|
+
"aria-label": "Resize chats panel"
|
|
7641
|
+
}
|
|
7642
|
+
)
|
|
7643
|
+
]
|
|
7644
|
+
}
|
|
7645
|
+
);
|
|
7646
|
+
}
|
|
7647
|
+
function SessionsListBody({
|
|
7648
|
+
sessions,
|
|
7649
|
+
isLoading,
|
|
7650
|
+
error,
|
|
7651
|
+
onRetry,
|
|
7652
|
+
selectedSessionId,
|
|
7653
|
+
onSelectSession,
|
|
7654
|
+
actions,
|
|
7655
|
+
compact = false,
|
|
7656
|
+
hasMore,
|
|
7657
|
+
isLoadingMore,
|
|
7658
|
+
onLoadMore
|
|
7659
|
+
}) {
|
|
7660
|
+
const [openMenuId, setOpenMenuId] = React.useState(null);
|
|
7661
|
+
const listRef = React.useRef(null);
|
|
7662
|
+
const [shadow, setShadow] = React.useState({ top: false, bottom: false });
|
|
7663
|
+
const updateShadow = React.useCallback(() => {
|
|
7664
|
+
const el = listRef.current;
|
|
7665
|
+
if (!el) return;
|
|
7666
|
+
const top = el.scrollTop > 1;
|
|
7667
|
+
const bottom = Math.ceil(el.scrollTop + el.clientHeight) < el.scrollHeight - 1;
|
|
7668
|
+
setShadow((s) => s.top === top && s.bottom === bottom ? s : { top, bottom });
|
|
7669
|
+
}, []);
|
|
7670
|
+
React.useEffect(() => {
|
|
7671
|
+
updateShadow();
|
|
7672
|
+
const el = listRef.current;
|
|
7673
|
+
if (!el) return;
|
|
7674
|
+
const ro = new ResizeObserver(updateShadow);
|
|
7675
|
+
ro.observe(el);
|
|
7676
|
+
return () => ro.disconnect();
|
|
7677
|
+
}, [sessions, isLoading, updateShadow]);
|
|
7678
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7679
|
+
"div",
|
|
7680
|
+
{
|
|
7681
|
+
className: cn(
|
|
7682
|
+
"payman-v2-sessions-list-wrap",
|
|
7683
|
+
shadow.top && "payman-v2-scroll-shadow-top",
|
|
7684
|
+
shadow.bottom && "payman-v2-scroll-shadow-bottom"
|
|
7685
|
+
),
|
|
7686
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7687
|
+
"div",
|
|
7688
|
+
{
|
|
7689
|
+
ref: listRef,
|
|
7690
|
+
onScroll: updateShadow,
|
|
7691
|
+
className: cn("payman-v2-sessions-list", compact && "payman-v2-sessions-list-compact"),
|
|
7692
|
+
children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(SessionsListSkeleton, {}) : error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-error", children: [
|
|
7693
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 18 }),
|
|
7694
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: error }),
|
|
7695
|
+
onRetry && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "payman-v2-sessions-retry-btn", onClick: onRetry, children: "Try again" })
|
|
7696
|
+
] }) : sessions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-empty", children: [
|
|
7697
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconMessage, { size: 20 }),
|
|
7698
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "No chats yet" })
|
|
7699
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7700
|
+
sessions.map((session) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7701
|
+
SessionRow,
|
|
7702
|
+
{
|
|
7703
|
+
session,
|
|
7704
|
+
isSelected: session.sessionId === selectedSessionId,
|
|
7705
|
+
isMenuOpen: openMenuId === session.sessionId,
|
|
7706
|
+
onSelect: () => onSelectSession(session.sessionId),
|
|
7707
|
+
onToggleMenu: () => setOpenMenuId((id) => id === session.sessionId ? null : session.sessionId),
|
|
7708
|
+
onCloseMenu: () => setOpenMenuId(null),
|
|
7709
|
+
actions
|
|
7710
|
+
},
|
|
7711
|
+
session.sessionId
|
|
7712
|
+
)),
|
|
7713
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7714
|
+
"button",
|
|
7715
|
+
{
|
|
7716
|
+
type: "button",
|
|
7717
|
+
className: "payman-v2-sessions-load-more-btn",
|
|
7718
|
+
onClick: onLoadMore,
|
|
7719
|
+
disabled: isLoadingMore,
|
|
7720
|
+
children: isLoadingMore ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-spinner payman-v2-spinner-sm" }) : "Load more"
|
|
7721
|
+
}
|
|
7722
|
+
)
|
|
7723
|
+
] })
|
|
7724
|
+
}
|
|
7725
|
+
)
|
|
7726
|
+
}
|
|
7727
|
+
);
|
|
7728
|
+
}
|
|
7729
|
+
function SessionsListSkeleton() {
|
|
7730
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "payman-v2-sessions-skeleton", children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-skeleton-row", children: [
|
|
7731
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7732
|
+
"div",
|
|
7733
|
+
{
|
|
7734
|
+
className: "payman-v2-sessions-skeleton-line payman-v2-sessions-skeleton-line-title",
|
|
7735
|
+
style: { animationDelay: `${i * 90}ms`, width: `${60 + i * 13 % 30}%` }
|
|
7736
|
+
}
|
|
7737
|
+
),
|
|
7738
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-skeleton-meta", children: [
|
|
7739
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7740
|
+
"div",
|
|
7741
|
+
{
|
|
7742
|
+
className: "payman-v2-sessions-skeleton-line payman-v2-sessions-skeleton-pill",
|
|
7743
|
+
style: { animationDelay: `${i * 90 + 60}ms` }
|
|
7744
|
+
}
|
|
7745
|
+
),
|
|
7746
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7747
|
+
"div",
|
|
7748
|
+
{
|
|
7749
|
+
className: "payman-v2-sessions-skeleton-line payman-v2-sessions-skeleton-pill",
|
|
7750
|
+
style: { animationDelay: `${i * 90 + 120}ms` }
|
|
7751
|
+
}
|
|
7752
|
+
)
|
|
7753
|
+
] })
|
|
7754
|
+
] }, i)) });
|
|
7755
|
+
}
|
|
7756
|
+
function SessionRow({
|
|
7757
|
+
session,
|
|
7758
|
+
isSelected,
|
|
7759
|
+
isMenuOpen,
|
|
7760
|
+
onSelect,
|
|
7761
|
+
onToggleMenu,
|
|
7762
|
+
onCloseMenu,
|
|
7763
|
+
actions
|
|
7764
|
+
}) {
|
|
7765
|
+
const menuRef = React.useRef(null);
|
|
7766
|
+
const clipRef = React.useRef(null);
|
|
7767
|
+
const textRef = React.useRef(null);
|
|
7768
|
+
const [overflowPx, setOverflowPx] = React.useState(0);
|
|
7769
|
+
const [scrolling, setScrolling] = React.useState(false);
|
|
7770
|
+
React.useEffect(() => {
|
|
7771
|
+
if (!isMenuOpen) return;
|
|
7772
|
+
const handlePointerDown = (event) => {
|
|
7773
|
+
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
7774
|
+
onCloseMenu();
|
|
7775
|
+
}
|
|
7776
|
+
};
|
|
7777
|
+
document.addEventListener("mousedown", handlePointerDown);
|
|
7778
|
+
return () => document.removeEventListener("mousedown", handlePointerDown);
|
|
7779
|
+
}, [isMenuOpen, onCloseMenu]);
|
|
7780
|
+
React.useEffect(() => {
|
|
7781
|
+
const clip = clipRef.current;
|
|
7782
|
+
const text = textRef.current;
|
|
7783
|
+
if (!clip || !text) return;
|
|
7784
|
+
const measure = () => setOverflowPx(Math.max(0, text.scrollWidth - clip.clientWidth));
|
|
7785
|
+
measure();
|
|
7786
|
+
const ro = new ResizeObserver(measure);
|
|
7787
|
+
ro.observe(clip);
|
|
7788
|
+
return () => ro.disconnect();
|
|
7789
|
+
}, [session.title]);
|
|
7790
|
+
const truncated = overflowPx > 2;
|
|
7791
|
+
const messageCount = session.messageCount ?? 0;
|
|
7792
|
+
const title = session.title?.trim() || "New chat";
|
|
7793
|
+
const relativeTime = formatRelativeTime(session.lastMessageAt);
|
|
7794
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7795
|
+
"div",
|
|
7796
|
+
{
|
|
7797
|
+
className: cn(
|
|
7798
|
+
"payman-v2-session-row",
|
|
7799
|
+
isSelected && "payman-v2-session-row-selected"
|
|
7800
|
+
),
|
|
7801
|
+
children: [
|
|
7802
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7803
|
+
"button",
|
|
7804
|
+
{
|
|
7805
|
+
type: "button",
|
|
7806
|
+
className: "payman-v2-session-row-main",
|
|
7807
|
+
onClick: onSelect,
|
|
7808
|
+
title,
|
|
7809
|
+
onMouseEnter: () => truncated && setScrolling(true),
|
|
7810
|
+
onMouseLeave: () => setScrolling(false),
|
|
7811
|
+
children: [
|
|
7812
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7813
|
+
"span",
|
|
7814
|
+
{
|
|
7815
|
+
ref: clipRef,
|
|
7816
|
+
className: "payman-v2-session-row-title",
|
|
7817
|
+
"data-truncated": truncated ? "true" : void 0,
|
|
7818
|
+
"data-scrolling": scrolling ? "true" : void 0,
|
|
7819
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7820
|
+
"span",
|
|
7821
|
+
{
|
|
7822
|
+
ref: textRef,
|
|
7823
|
+
className: "payman-v2-session-row-title-text",
|
|
7824
|
+
style: scrolling ? {
|
|
7825
|
+
// +16 so the last chars clear the right-edge fade mask.
|
|
7826
|
+
transform: `translateX(-${overflowPx + 16}px)`,
|
|
7827
|
+
// Constant reading pace (~38px/s), so it moves at the same
|
|
7828
|
+
// speed from start to end rather than easing in/out.
|
|
7829
|
+
transitionDuration: `${Math.max(0.9, (overflowPx + 16) / 38)}s`
|
|
7830
|
+
} : void 0,
|
|
7831
|
+
children: title
|
|
7832
|
+
}
|
|
7833
|
+
)
|
|
7834
|
+
}
|
|
7835
|
+
),
|
|
7836
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-session-row-meta", children: [
|
|
7837
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-session-row-meta-item", children: [
|
|
7838
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconMessage, { size: 12 }),
|
|
7839
|
+
messageCount,
|
|
7840
|
+
" ",
|
|
7841
|
+
messageCount === 1 ? "message" : "messages"
|
|
7842
|
+
] }),
|
|
7843
|
+
relativeTime && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-session-row-meta-item", children: [
|
|
7844
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconClock, { size: 12 }),
|
|
7845
|
+
relativeTime
|
|
7846
|
+
] })
|
|
7847
|
+
] })
|
|
7848
|
+
]
|
|
7849
|
+
}
|
|
7850
|
+
),
|
|
7851
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-session-row-menu-wrap", ref: menuRef, children: [
|
|
7852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7853
|
+
"button",
|
|
7854
|
+
{
|
|
7855
|
+
type: "button",
|
|
7856
|
+
className: cn(
|
|
7857
|
+
"payman-v2-session-row-menu-btn",
|
|
7858
|
+
isMenuOpen && "payman-v2-session-row-menu-btn-active"
|
|
7859
|
+
),
|
|
7860
|
+
onClick: onToggleMenu,
|
|
7861
|
+
"aria-label": "Chat options",
|
|
7862
|
+
"aria-expanded": isMenuOpen,
|
|
7863
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { size: 14 })
|
|
7864
|
+
}
|
|
7865
|
+
),
|
|
7866
|
+
isMenuOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-session-row-menu", role: "menu", children: actions.map((action) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7867
|
+
"button",
|
|
7868
|
+
{
|
|
7869
|
+
type: "button",
|
|
7870
|
+
role: "menuitem",
|
|
7871
|
+
className: cn(
|
|
7872
|
+
"payman-v2-session-row-menu-item",
|
|
7873
|
+
action.destructive && "payman-v2-session-row-menu-item-destructive"
|
|
7874
|
+
),
|
|
7875
|
+
onClick: () => {
|
|
7876
|
+
onCloseMenu();
|
|
7877
|
+
void action.onSelect(session);
|
|
7878
|
+
},
|
|
7879
|
+
children: action.label
|
|
7880
|
+
},
|
|
7881
|
+
action.key
|
|
7882
|
+
)) })
|
|
7883
|
+
] })
|
|
7884
|
+
]
|
|
7885
|
+
}
|
|
7886
|
+
);
|
|
7887
|
+
}
|
|
7888
|
+
var CLOSE_DELAY_MS = 150;
|
|
7889
|
+
var HOVER_OPEN_DELAY_MS = 500;
|
|
7890
|
+
function SessionsPeekPopoverV2({
|
|
7891
|
+
title,
|
|
7892
|
+
newChatLabel,
|
|
7893
|
+
sessions,
|
|
7894
|
+
isLoading,
|
|
7895
|
+
error,
|
|
7896
|
+
onRetry,
|
|
7897
|
+
selectedSessionId,
|
|
7898
|
+
onSelectSession,
|
|
7899
|
+
onNewSession,
|
|
7900
|
+
onExpand,
|
|
7901
|
+
actions
|
|
7902
|
+
}) {
|
|
7903
|
+
const [open, setOpen] = React.useState(false);
|
|
7904
|
+
const closeTimerRef = React.useRef(null);
|
|
7905
|
+
const openTimerRef = React.useRef(null);
|
|
7906
|
+
const cancelClose = React.useCallback(() => {
|
|
7907
|
+
if (closeTimerRef.current) {
|
|
7908
|
+
clearTimeout(closeTimerRef.current);
|
|
7909
|
+
closeTimerRef.current = null;
|
|
7910
|
+
}
|
|
7911
|
+
}, []);
|
|
7912
|
+
const cancelOpen = React.useCallback(() => {
|
|
7913
|
+
if (openTimerRef.current) {
|
|
7914
|
+
clearTimeout(openTimerRef.current);
|
|
7915
|
+
openTimerRef.current = null;
|
|
7916
|
+
}
|
|
7917
|
+
}, []);
|
|
7918
|
+
const scheduleClose = React.useCallback(() => {
|
|
7919
|
+
cancelOpen();
|
|
7920
|
+
cancelClose();
|
|
7921
|
+
closeTimerRef.current = setTimeout(() => setOpen(false), CLOSE_DELAY_MS);
|
|
7922
|
+
}, [cancelOpen, cancelClose]);
|
|
7923
|
+
const handleEnter = React.useCallback(() => {
|
|
7924
|
+
cancelClose();
|
|
7925
|
+
cancelOpen();
|
|
7926
|
+
openTimerRef.current = setTimeout(() => setOpen(true), HOVER_OPEN_DELAY_MS);
|
|
7927
|
+
}, [cancelClose, cancelOpen]);
|
|
7928
|
+
React.useEffect(
|
|
7929
|
+
() => () => {
|
|
7930
|
+
cancelOpen();
|
|
7931
|
+
cancelClose();
|
|
7932
|
+
},
|
|
7933
|
+
[cancelOpen, cancelClose]
|
|
7934
|
+
);
|
|
7935
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7936
|
+
"div",
|
|
7937
|
+
{
|
|
7938
|
+
className: "payman-v2-sessions-peek-anchor",
|
|
7939
|
+
onMouseEnter: handleEnter,
|
|
7940
|
+
onMouseLeave: scheduleClose,
|
|
7941
|
+
children: [
|
|
7942
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7943
|
+
"button",
|
|
7944
|
+
{
|
|
7945
|
+
type: "button",
|
|
7946
|
+
className: "payman-v2-sessions-reopen-btn",
|
|
7947
|
+
onClick: onExpand,
|
|
7948
|
+
"aria-label": "Show chats",
|
|
7949
|
+
title: "Show chats",
|
|
7950
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { size: 16 })
|
|
7951
|
+
}
|
|
7952
|
+
),
|
|
7953
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-peek", role: "dialog", "aria-label": title, children: [
|
|
7954
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-sessions-peek-header", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-sessions-peek-title", children: title }) }),
|
|
7955
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7956
|
+
"button",
|
|
7957
|
+
{
|
|
7958
|
+
type: "button",
|
|
7959
|
+
className: "payman-v2-sessions-new-btn payman-v2-sessions-peek-new-btn",
|
|
7960
|
+
onClick: () => {
|
|
7961
|
+
onNewSession();
|
|
7962
|
+
setOpen(false);
|
|
7963
|
+
},
|
|
7964
|
+
children: [
|
|
7965
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconNewChat, { size: 14 }),
|
|
7966
|
+
newChatLabel
|
|
7967
|
+
]
|
|
6190
7968
|
}
|
|
6191
|
-
)
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
});
|
|
6196
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
6197
|
-
bars,
|
|
6198
|
-
unaccountedMs > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 8 }, children: [
|
|
6199
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6200
|
-
"div",
|
|
6201
|
-
{
|
|
6202
|
-
style: {
|
|
6203
|
-
display: "flex",
|
|
6204
|
-
justifyContent: "space-between",
|
|
6205
|
-
fontSize: 12,
|
|
6206
|
-
marginBottom: 4,
|
|
6207
|
-
fontFamily: "ui-monospace, SFMono-Regular, monospace",
|
|
6208
|
-
opacity: 0.7
|
|
6209
|
-
},
|
|
6210
|
-
children: [
|
|
6211
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "(unaccounted)" }),
|
|
6212
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatMs(unaccountedMs) })
|
|
6213
|
-
]
|
|
6214
|
-
}
|
|
6215
|
-
),
|
|
6216
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6217
|
-
"div",
|
|
6218
|
-
{
|
|
6219
|
-
style: {
|
|
6220
|
-
height: 8,
|
|
6221
|
-
background: "rgba(255,255,255,0.06)",
|
|
6222
|
-
borderRadius: 4,
|
|
6223
|
-
overflow: "hidden"
|
|
6224
|
-
},
|
|
6225
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6226
|
-
"div",
|
|
7969
|
+
),
|
|
7970
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
7971
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7972
|
+
SessionsListBody,
|
|
6227
7973
|
{
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
7974
|
+
sessions,
|
|
7975
|
+
isLoading,
|
|
7976
|
+
error,
|
|
7977
|
+
onRetry,
|
|
7978
|
+
selectedSessionId,
|
|
7979
|
+
onSelectSession: (sessionId) => {
|
|
7980
|
+
onSelectSession(sessionId);
|
|
7981
|
+
setOpen(false);
|
|
7982
|
+
},
|
|
7983
|
+
actions,
|
|
7984
|
+
compact: true
|
|
6233
7985
|
}
|
|
6234
7986
|
)
|
|
6235
|
-
}
|
|
6236
|
-
|
|
6237
|
-
|
|
7987
|
+
] })
|
|
7988
|
+
]
|
|
7989
|
+
}
|
|
7990
|
+
);
|
|
7991
|
+
}
|
|
7992
|
+
function SessionsBottomSheetV2({
|
|
7993
|
+
title,
|
|
7994
|
+
newChatLabel,
|
|
7995
|
+
sessions,
|
|
7996
|
+
isLoading,
|
|
7997
|
+
error,
|
|
7998
|
+
onRetry,
|
|
7999
|
+
selectedSessionId,
|
|
8000
|
+
onSelectSession,
|
|
8001
|
+
onNewSession,
|
|
8002
|
+
onClose,
|
|
8003
|
+
actions,
|
|
8004
|
+
hasMore,
|
|
8005
|
+
isLoadingMore,
|
|
8006
|
+
onLoadMore
|
|
8007
|
+
}) {
|
|
8008
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8009
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8010
|
+
framerMotion.motion.div,
|
|
8011
|
+
{
|
|
8012
|
+
className: "payman-v2-sessions-sheet-backdrop",
|
|
8013
|
+
initial: { opacity: 0 },
|
|
8014
|
+
animate: { opacity: 1 },
|
|
8015
|
+
exit: { opacity: 0 },
|
|
8016
|
+
transition: { duration: 0.2 },
|
|
8017
|
+
onClick: onClose
|
|
8018
|
+
}
|
|
8019
|
+
),
|
|
6238
8020
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6239
|
-
|
|
8021
|
+
framerMotion.motion.div,
|
|
6240
8022
|
{
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
},
|
|
8023
|
+
className: "payman-v2-sessions-sheet",
|
|
8024
|
+
role: "dialog",
|
|
8025
|
+
"aria-modal": "true",
|
|
8026
|
+
"aria-label": title,
|
|
8027
|
+
initial: { y: "100%" },
|
|
8028
|
+
animate: { y: 0 },
|
|
8029
|
+
exit: { y: "100%" },
|
|
8030
|
+
transition: { type: "spring", damping: 32, stiffness: 320 },
|
|
6250
8031
|
children: [
|
|
6251
|
-
/* @__PURE__ */ jsxRuntime.
|
|
6252
|
-
|
|
6253
|
-
"
|
|
6254
|
-
|
|
8032
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-sessions-sheet-grabber", "aria-hidden": true }),
|
|
8033
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-sessions-header", children: [
|
|
8034
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-sessions-title", children: title }),
|
|
8035
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8036
|
+
"button",
|
|
8037
|
+
{
|
|
8038
|
+
type: "button",
|
|
8039
|
+
className: "payman-v2-sessions-close",
|
|
8040
|
+
onClick: onClose,
|
|
8041
|
+
"aria-label": "Close chats panel",
|
|
8042
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 })
|
|
8043
|
+
}
|
|
8044
|
+
)
|
|
6255
8045
|
] }),
|
|
6256
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
] })
|
|
8046
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "payman-v2-sessions-new-btn", onClick: onNewSession, children: [
|
|
8047
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconNewChat, { size: 16 }),
|
|
8048
|
+
newChatLabel
|
|
8049
|
+
] }),
|
|
8050
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
8051
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8052
|
+
SessionsListBody,
|
|
8053
|
+
{
|
|
8054
|
+
sessions,
|
|
8055
|
+
isLoading,
|
|
8056
|
+
error,
|
|
8057
|
+
onRetry,
|
|
8058
|
+
selectedSessionId,
|
|
8059
|
+
onSelectSession,
|
|
8060
|
+
actions,
|
|
8061
|
+
hasMore,
|
|
8062
|
+
isLoadingMore,
|
|
8063
|
+
onLoadMore
|
|
8064
|
+
}
|
|
8065
|
+
)
|
|
6260
8066
|
]
|
|
6261
8067
|
}
|
|
6262
8068
|
)
|
|
@@ -6356,7 +8162,8 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6356
8162
|
onLoadMoreMessages,
|
|
6357
8163
|
isLoadingMoreMessages = false,
|
|
6358
8164
|
hasMoreMessages = false,
|
|
6359
|
-
chat
|
|
8165
|
+
chat,
|
|
8166
|
+
sessionsPanel
|
|
6360
8167
|
}, ref) {
|
|
6361
8168
|
const [inputValue, setInputValue] = React.useState("");
|
|
6362
8169
|
const prevInputValueRef = React.useRef(inputValue);
|
|
@@ -6369,6 +8176,25 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6369
8176
|
const chatInputV2Ref = React.useRef(null);
|
|
6370
8177
|
const messageListV2Ref = React.useRef(null);
|
|
6371
8178
|
const resetToEmptyStateRef = React.useRef(false);
|
|
8179
|
+
const rootRef = React.useRef(null);
|
|
8180
|
+
const [isCompact, setIsCompact] = React.useState(false);
|
|
8181
|
+
React.useEffect(() => {
|
|
8182
|
+
const el = rootRef.current;
|
|
8183
|
+
if (!el) return;
|
|
8184
|
+
const ro = new ResizeObserver((entries) => {
|
|
8185
|
+
const width = entries[0]?.contentRect.width;
|
|
8186
|
+
if (width != null) setIsCompact(width < COMPACT_BREAKPOINT_PX);
|
|
8187
|
+
});
|
|
8188
|
+
ro.observe(el);
|
|
8189
|
+
return () => ro.disconnect();
|
|
8190
|
+
}, []);
|
|
8191
|
+
const wasCompactRef = React.useRef(isCompact);
|
|
8192
|
+
React.useEffect(() => {
|
|
8193
|
+
if (isCompact && !wasCompactRef.current && sessionsPanel?.open) {
|
|
8194
|
+
sessionsPanel.onToggle();
|
|
8195
|
+
}
|
|
8196
|
+
wasCompactRef.current = isCompact;
|
|
8197
|
+
}, [isCompact, sessionsPanel]);
|
|
6372
8198
|
React.useEffect(() => {
|
|
6373
8199
|
if (config.sentryDsn) {
|
|
6374
8200
|
initSentryIfNeeded(config.sentryDsn);
|
|
@@ -6413,6 +8239,15 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6413
8239
|
const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
|
|
6414
8240
|
const dismissNotification = chat.dismissNotification ?? NOOP;
|
|
6415
8241
|
const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
|
|
8242
|
+
const expiredUserActionIdsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
8243
|
+
const expireUserActionOnce = React.useCallback(
|
|
8244
|
+
(userActionId) => {
|
|
8245
|
+
if (expiredUserActionIdsRef.current.has(userActionId)) return;
|
|
8246
|
+
expiredUserActionIdsRef.current.add(userActionId);
|
|
8247
|
+
void expireUserAction2(userActionId);
|
|
8248
|
+
},
|
|
8249
|
+
[expireUserAction2]
|
|
8250
|
+
);
|
|
6416
8251
|
const {
|
|
6417
8252
|
transcribedText,
|
|
6418
8253
|
isAvailable: voiceAvailable,
|
|
@@ -6514,13 +8349,20 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6514
8349
|
if (isRecording) {
|
|
6515
8350
|
stopRecording();
|
|
6516
8351
|
}
|
|
6517
|
-
|
|
8352
|
+
if (sessionsPanel?.onNewSession) {
|
|
8353
|
+
sessionsPanel.onNewSession();
|
|
8354
|
+
if (isCompact && sessionsPanel.open) sessionsPanel.onToggle();
|
|
8355
|
+
} else {
|
|
8356
|
+
resetSession();
|
|
8357
|
+
}
|
|
6518
8358
|
onResetSession?.();
|
|
6519
8359
|
}, [
|
|
6520
8360
|
clearTranscript,
|
|
6521
8361
|
isRecording,
|
|
8362
|
+
isCompact,
|
|
6522
8363
|
onResetSession,
|
|
6523
8364
|
resetSession,
|
|
8365
|
+
sessionsPanel,
|
|
6524
8366
|
stopRecording
|
|
6525
8367
|
]);
|
|
6526
8368
|
const requestResetSession = React.useCallback(() => {
|
|
@@ -6534,8 +8376,9 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6534
8376
|
clearMessages,
|
|
6535
8377
|
cancelStream,
|
|
6536
8378
|
getSessionId,
|
|
6537
|
-
getMessages
|
|
6538
|
-
|
|
8379
|
+
getMessages,
|
|
8380
|
+
refreshSessions: sessionsPanel?.refetch ?? NOOP
|
|
8381
|
+
}), [performResetSession, clearMessages, cancelStream, getSessionId, getMessages, sessionsPanel?.refetch]);
|
|
6539
8382
|
const {
|
|
6540
8383
|
placeholder = "Type your message...",
|
|
6541
8384
|
emptyStateText = "What can I help with?",
|
|
@@ -6655,6 +8498,13 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6655
8498
|
};
|
|
6656
8499
|
const userActionPrompts = isUserActionSupported ? userActionState.prompts : void 0;
|
|
6657
8500
|
const notifications = userActionState.notifications;
|
|
8501
|
+
const dockableUserActionPrompts = userActionPrompts?.filter(
|
|
8502
|
+
(prompt) => prompt.kind !== "notification" && (prompt.status === "pending" || prompt.status === "submitting" || prompt.status === "stale")
|
|
8503
|
+
);
|
|
8504
|
+
const dockedPendingPrompts = dockableUserActionPrompts?.filter(
|
|
8505
|
+
(prompt) => prompt.status === "pending"
|
|
8506
|
+
);
|
|
8507
|
+
const dockedPrompt = dockedPendingPrompts?.[dockedPendingPrompts.length - 1] ?? dockableUserActionPrompts?.[dockableUserActionPrompts.length - 1];
|
|
6658
8508
|
const handleV2Send = (text) => {
|
|
6659
8509
|
if (isRecording) stopRecording();
|
|
6660
8510
|
if (text.trim() && !disableInput && isSessionParamsConfigured) {
|
|
@@ -6703,160 +8553,236 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6703
8553
|
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6704
8554
|
"div",
|
|
6705
8555
|
{
|
|
8556
|
+
ref: rootRef,
|
|
6706
8557
|
className: cn("payman-v2-root", className),
|
|
6707
8558
|
style,
|
|
6708
8559
|
children: [
|
|
6709
8560
|
children,
|
|
6710
|
-
/* @__PURE__ */ jsxRuntime.
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
8561
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-body", children: [
|
|
8562
|
+
sessionsPanel && !isCompact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8563
|
+
SessionsSidebarV2,
|
|
8564
|
+
{
|
|
8565
|
+
open: sessionsPanel.open,
|
|
8566
|
+
onClose: sessionsPanel.onToggle,
|
|
8567
|
+
title: sessionsPanel.title,
|
|
8568
|
+
newChatLabel: sessionsPanel.newChatLabel,
|
|
8569
|
+
sessions: sessionsPanel.sessionsList,
|
|
8570
|
+
isLoading: sessionsPanel.isLoadingList,
|
|
8571
|
+
error: sessionsPanel.listError,
|
|
8572
|
+
onRetry: sessionsPanel.refetch,
|
|
8573
|
+
selectedSessionId: sessionsPanel.activeSessionId,
|
|
8574
|
+
onSelectSession: sessionsPanel.onSelectSession,
|
|
8575
|
+
onNewSession: requestResetSession,
|
|
8576
|
+
actions: sessionsPanel.actions,
|
|
8577
|
+
hasMore: sessionsPanel.hasMore,
|
|
8578
|
+
isLoadingMore: sessionsPanel.isLoadingMore,
|
|
8579
|
+
onLoadMore: sessionsPanel.onLoadMore
|
|
8580
|
+
}
|
|
8581
|
+
),
|
|
8582
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: sessionsPanel && isCompact && sessionsPanel.open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8583
|
+
SessionsBottomSheetV2,
|
|
8584
|
+
{
|
|
8585
|
+
title: sessionsPanel.title,
|
|
8586
|
+
newChatLabel: sessionsPanel.newChatLabel,
|
|
8587
|
+
sessions: sessionsPanel.sessionsList,
|
|
8588
|
+
isLoading: sessionsPanel.isLoadingList,
|
|
8589
|
+
error: sessionsPanel.listError,
|
|
8590
|
+
onRetry: sessionsPanel.refetch,
|
|
8591
|
+
selectedSessionId: sessionsPanel.activeSessionId,
|
|
8592
|
+
onSelectSession: (sessionId) => {
|
|
8593
|
+
sessionsPanel.onSelectSession(sessionId);
|
|
8594
|
+
sessionsPanel.onToggle();
|
|
8595
|
+
},
|
|
8596
|
+
onNewSession: requestResetSession,
|
|
8597
|
+
onClose: sessionsPanel.onToggle,
|
|
8598
|
+
actions: sessionsPanel.actions,
|
|
8599
|
+
hasMore: sessionsPanel.hasMore,
|
|
8600
|
+
isLoadingMore: sessionsPanel.isLoadingMore,
|
|
8601
|
+
onLoadMore: sessionsPanel.onLoadMore
|
|
8602
|
+
},
|
|
8603
|
+
"sessions-bottom-sheet"
|
|
8604
|
+
) }),
|
|
8605
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-chat-column", children: [
|
|
8606
|
+
sessionsPanel?.isLoadingMessages && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-messages-loading-overlay", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-spinner" }) }),
|
|
8607
|
+
sessionsPanel && !sessionsPanel.open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8608
|
+
SessionsPeekPopoverV2,
|
|
8609
|
+
{
|
|
8610
|
+
title: sessionsPanel.title,
|
|
8611
|
+
newChatLabel: sessionsPanel.newChatLabel,
|
|
8612
|
+
sessions: sessionsPanel.sessionsList,
|
|
8613
|
+
isLoading: sessionsPanel.isLoadingList,
|
|
8614
|
+
error: sessionsPanel.listError,
|
|
8615
|
+
onRetry: sessionsPanel.refetch,
|
|
8616
|
+
selectedSessionId: sessionsPanel.activeSessionId,
|
|
8617
|
+
onSelectSession: sessionsPanel.onSelectSession,
|
|
8618
|
+
onNewSession: requestResetSession,
|
|
8619
|
+
onExpand: sessionsPanel.onToggle,
|
|
8620
|
+
actions: sessionsPanel.actions
|
|
8621
|
+
}
|
|
8622
|
+
),
|
|
8623
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8624
|
+
framerMotion.motion.div,
|
|
8625
|
+
{
|
|
8626
|
+
initial: { opacity: 1 },
|
|
8627
|
+
exit: { opacity: 0 },
|
|
8628
|
+
transition: { duration: 0.3 },
|
|
8629
|
+
className: "payman-v2-chat-layout",
|
|
8630
|
+
style: { justifyContent: "center", alignItems: "center" },
|
|
8631
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1, width: "100%" }, children: [
|
|
8632
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8633
|
+
MessageList,
|
|
8634
|
+
{
|
|
8635
|
+
messages,
|
|
8636
|
+
isLoading: false,
|
|
8637
|
+
emptyStateText,
|
|
8638
|
+
showEmptyStateIcon,
|
|
8639
|
+
emptyStateComponent,
|
|
8640
|
+
layout,
|
|
8641
|
+
showTimestamps,
|
|
8642
|
+
stage: config.stage || "DEVELOPMENT",
|
|
8643
|
+
animated,
|
|
8644
|
+
showAgentName,
|
|
8645
|
+
agentName,
|
|
8646
|
+
showAvatars,
|
|
8647
|
+
showUserAvatar,
|
|
8648
|
+
showAssistantAvatar,
|
|
8649
|
+
showExecutionSteps,
|
|
8650
|
+
showStreamingDot,
|
|
8651
|
+
streamingStepsText,
|
|
8652
|
+
completedStepsText,
|
|
8653
|
+
onExecutionTraceClick,
|
|
8654
|
+
onLoadMoreMessages,
|
|
8655
|
+
isLoadingMoreMessages,
|
|
8656
|
+
hasMoreMessages
|
|
8657
|
+
}
|
|
8658
|
+
),
|
|
8659
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8660
|
+
framerMotion.motion.div,
|
|
8661
|
+
{
|
|
8662
|
+
initial: { opacity: 0 },
|
|
8663
|
+
animate: { opacity: 1 },
|
|
8664
|
+
transition: { duration: 0.18 },
|
|
8665
|
+
style: { width: "100%" },
|
|
8666
|
+
children: hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8667
|
+
ChatInputV2,
|
|
8668
|
+
{
|
|
8669
|
+
ref: chatInputV2Ref,
|
|
8670
|
+
onSend: handleV2Send,
|
|
8671
|
+
onCancel: cancelStream,
|
|
8672
|
+
disabled: isV2InputDisabled,
|
|
8673
|
+
isStreaming: isWaitingForResponse,
|
|
8674
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
8675
|
+
enableVoice: config.enableVoice === true,
|
|
8676
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
8677
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
8678
|
+
isRecording,
|
|
8679
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
8680
|
+
onCancelRecording: handleCancelRecording,
|
|
8681
|
+
onConfirmRecording: handleConfirmRecording,
|
|
8682
|
+
showResetSession,
|
|
8683
|
+
onResetSession: requestResetSession,
|
|
8684
|
+
showAttachmentButton,
|
|
8685
|
+
showUploadImageButton,
|
|
8686
|
+
showAttachFileButton,
|
|
8687
|
+
onUploadImageClick,
|
|
8688
|
+
onAttachFileClick,
|
|
8689
|
+
editingMessageId,
|
|
8690
|
+
onClearEditing: handleClearEditing,
|
|
8691
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
8692
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
8693
|
+
slashCommands
|
|
8694
|
+
}
|
|
8695
|
+
)
|
|
8696
|
+
}
|
|
8697
|
+
)
|
|
8698
|
+
] })
|
|
8699
|
+
},
|
|
8700
|
+
"v2-empty"
|
|
8701
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8702
|
+
framerMotion.motion.div,
|
|
8703
|
+
{
|
|
8704
|
+
initial: { opacity: 0 },
|
|
8705
|
+
animate: { opacity: 1 },
|
|
8706
|
+
transition: { duration: 0.25 },
|
|
8707
|
+
className: "payman-v2-chat-layout",
|
|
8708
|
+
children: [
|
|
8709
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8710
|
+
MessageListV2,
|
|
8711
|
+
{
|
|
8712
|
+
ref: messageListV2Ref,
|
|
8713
|
+
messages,
|
|
8714
|
+
isStreaming: isWaitingForResponse,
|
|
8715
|
+
onEditUserMessage: handleEditMessageDraft,
|
|
8716
|
+
onRetryUserMessage: handleRetryUserMessage,
|
|
8717
|
+
onImageClick: handleImageClick,
|
|
8718
|
+
onExecutionTraceClick,
|
|
8719
|
+
messageActions,
|
|
8720
|
+
retryDisabled: isWaitingForResponse,
|
|
8721
|
+
typingSpeed: config.typingSpeed ?? 4,
|
|
8722
|
+
userActionPrompts,
|
|
8723
|
+
dockedUserActionId: dockedPrompt?.userActionId,
|
|
8724
|
+
notifications,
|
|
8725
|
+
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
8726
|
+
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
8727
|
+
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
8728
|
+
onExpireUserAction: isUserActionSupported ? async (id) => expireUserActionOnce(id) : void 0,
|
|
8729
|
+
onDismissNotification: dismissNotification,
|
|
8730
|
+
onSubmitFeedback: handleSubmitFeedback
|
|
8731
|
+
}
|
|
8732
|
+
),
|
|
8733
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8734
|
+
StreamingIndicatorV2,
|
|
6755
8735
|
{
|
|
6756
|
-
ref: chatInputV2Ref,
|
|
6757
|
-
onSend: handleV2Send,
|
|
6758
|
-
onCancel: cancelStream,
|
|
6759
|
-
disabled: isV2InputDisabled,
|
|
6760
8736
|
isStreaming: isWaitingForResponse,
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
8737
|
+
loadingAnimation: config.loadingAnimation
|
|
8738
|
+
}
|
|
8739
|
+
),
|
|
8740
|
+
hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8741
|
+
UserActionDock,
|
|
8742
|
+
{
|
|
8743
|
+
prompt: isUserActionSupported ? dockedPrompt : void 0,
|
|
8744
|
+
onSubmit: submitUserAction2,
|
|
8745
|
+
onCancel: cancelUserAction2,
|
|
8746
|
+
onResend: resendUserAction2,
|
|
8747
|
+
onExpired: expireUserActionOnce,
|
|
8748
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8749
|
+
ChatInputV2,
|
|
8750
|
+
{
|
|
8751
|
+
ref: chatInputV2Ref,
|
|
8752
|
+
onSend: handleV2Send,
|
|
8753
|
+
onCancel: cancelStream,
|
|
8754
|
+
disabled: isV2InputDisabled,
|
|
8755
|
+
isStreaming: isWaitingForResponse,
|
|
8756
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
8757
|
+
enableVoice: config.enableVoice === true,
|
|
8758
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
8759
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
8760
|
+
isRecording,
|
|
8761
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
8762
|
+
onCancelRecording: handleCancelRecording,
|
|
8763
|
+
onConfirmRecording: handleConfirmRecording,
|
|
8764
|
+
showResetSession,
|
|
8765
|
+
onResetSession: requestResetSession,
|
|
8766
|
+
showAttachmentButton,
|
|
8767
|
+
showUploadImageButton,
|
|
8768
|
+
showAttachFileButton,
|
|
8769
|
+
onUploadImageClick,
|
|
8770
|
+
onAttachFileClick,
|
|
8771
|
+
editingMessageId,
|
|
8772
|
+
onClearEditing: handleClearEditing,
|
|
8773
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
8774
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
8775
|
+
slashCommands
|
|
8776
|
+
}
|
|
8777
|
+
)
|
|
6781
8778
|
}
|
|
6782
8779
|
)
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
)
|
|
6789
|
-
framerMotion.motion.div,
|
|
6790
|
-
{
|
|
6791
|
-
initial: hasEverSentMessage ? { opacity: 0 } : false,
|
|
6792
|
-
animate: { opacity: 1 },
|
|
6793
|
-
transition: { duration: 0.3 },
|
|
6794
|
-
className: "payman-v2-chat-layout",
|
|
6795
|
-
children: [
|
|
6796
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6797
|
-
MessageListV2,
|
|
6798
|
-
{
|
|
6799
|
-
ref: messageListV2Ref,
|
|
6800
|
-
messages,
|
|
6801
|
-
isStreaming: isWaitingForResponse,
|
|
6802
|
-
onEditUserMessage: handleEditMessageDraft,
|
|
6803
|
-
onRetryUserMessage: handleRetryUserMessage,
|
|
6804
|
-
onImageClick: handleImageClick,
|
|
6805
|
-
onExecutionTraceClick,
|
|
6806
|
-
messageActions,
|
|
6807
|
-
retryDisabled: isWaitingForResponse,
|
|
6808
|
-
typingSpeed: config.typingSpeed ?? 4,
|
|
6809
|
-
userActionPrompts,
|
|
6810
|
-
notifications,
|
|
6811
|
-
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
6812
|
-
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
6813
|
-
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
6814
|
-
onExpireUserAction: isUserActionSupported ? expireUserAction2 : void 0,
|
|
6815
|
-
onDismissNotification: dismissNotification,
|
|
6816
|
-
onSubmitFeedback: handleSubmitFeedback
|
|
6817
|
-
}
|
|
6818
|
-
),
|
|
6819
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6820
|
-
StreamingIndicatorV2,
|
|
6821
|
-
{
|
|
6822
|
-
isStreaming: isWaitingForResponse,
|
|
6823
|
-
loadingAnimation: config.loadingAnimation
|
|
6824
|
-
}
|
|
6825
|
-
),
|
|
6826
|
-
hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6827
|
-
ChatInputV2,
|
|
6828
|
-
{
|
|
6829
|
-
ref: chatInputV2Ref,
|
|
6830
|
-
onSend: handleV2Send,
|
|
6831
|
-
onCancel: cancelStream,
|
|
6832
|
-
disabled: isV2InputDisabled,
|
|
6833
|
-
isStreaming: isWaitingForResponse,
|
|
6834
|
-
placeholder: isRecording ? "Listening..." : placeholder,
|
|
6835
|
-
enableVoice: config.enableVoice === true,
|
|
6836
|
-
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
6837
|
-
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
6838
|
-
isRecording,
|
|
6839
|
-
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
6840
|
-
onCancelRecording: handleCancelRecording,
|
|
6841
|
-
onConfirmRecording: handleConfirmRecording,
|
|
6842
|
-
showResetSession,
|
|
6843
|
-
onResetSession: requestResetSession,
|
|
6844
|
-
showAttachmentButton,
|
|
6845
|
-
showUploadImageButton,
|
|
6846
|
-
showAttachFileButton,
|
|
6847
|
-
onUploadImageClick,
|
|
6848
|
-
onAttachFileClick,
|
|
6849
|
-
editingMessageId,
|
|
6850
|
-
onClearEditing: handleClearEditing,
|
|
6851
|
-
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
6852
|
-
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
6853
|
-
slashCommands
|
|
6854
|
-
}
|
|
6855
|
-
)
|
|
6856
|
-
]
|
|
6857
|
-
},
|
|
6858
|
-
"v2-chat"
|
|
6859
|
-
) }),
|
|
8780
|
+
]
|
|
8781
|
+
},
|
|
8782
|
+
"v2-chat"
|
|
8783
|
+
) })
|
|
8784
|
+
] })
|
|
8785
|
+
] }),
|
|
6860
8786
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6861
8787
|
ImageLightboxV2,
|
|
6862
8788
|
{
|
|
@@ -6887,13 +8813,162 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
6887
8813
|
}
|
|
6888
8814
|
) });
|
|
6889
8815
|
});
|
|
6890
|
-
var
|
|
6891
|
-
function
|
|
8816
|
+
var PaymanChatWithChat = React.forwardRef(
|
|
8817
|
+
function PaymanChatWithChat2(props, ref) {
|
|
6892
8818
|
const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
|
|
6893
8819
|
const chat = useChatV2(props.config, mergedCallbacks);
|
|
6894
8820
|
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatInner, { ...props, chat, ref });
|
|
6895
8821
|
}
|
|
6896
8822
|
);
|
|
8823
|
+
function AvailabilityNotice({ message }) {
|
|
8824
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground text-sm", children: message }) }) });
|
|
8825
|
+
}
|
|
8826
|
+
var DEFAULT_AGENT_DISABLED_MESSAGE = "Chat is currently unavailable. Please try again later.";
|
|
8827
|
+
var DEFAULT_USER_BLOCKED_MESSAGE = "Chat isn't available for your account right now.";
|
|
8828
|
+
var COMPACT_BREAKPOINT_PX = 640;
|
|
8829
|
+
var PaymanChat = React.forwardRef(
|
|
8830
|
+
function PaymanChat2(props, ref) {
|
|
8831
|
+
const { config } = props;
|
|
8832
|
+
const sessionsConfig = config.sessions;
|
|
8833
|
+
const availabilityData = useAgentConfig({
|
|
8834
|
+
api: config.api,
|
|
8835
|
+
availability: config.availability
|
|
8836
|
+
});
|
|
8837
|
+
const agentUnavailable = availabilityData.enabled && availabilityData.available === false;
|
|
8838
|
+
const availabilityStatus = availabilityData.status;
|
|
8839
|
+
const availabilityGateOpen = !availabilityData.enabled || availabilityData.available === true || availabilityData.available === null && !availabilityData.isLoading;
|
|
8840
|
+
const gatedSessionsConfig = React.useMemo(
|
|
8841
|
+
() => sessionsConfig ? {
|
|
8842
|
+
...sessionsConfig,
|
|
8843
|
+
enabled: sessionsConfig.enabled === true && availabilityGateOpen
|
|
8844
|
+
} : sessionsConfig,
|
|
8845
|
+
[sessionsConfig, availabilityGateOpen]
|
|
8846
|
+
);
|
|
8847
|
+
const sessionsData = useChatSessions({
|
|
8848
|
+
api: config.api,
|
|
8849
|
+
sessions: gatedSessionsConfig,
|
|
8850
|
+
initialSessionId: config.initialSessionId
|
|
8851
|
+
});
|
|
8852
|
+
const [sidebarOpen, setSidebarOpen] = React.useState(
|
|
8853
|
+
sessionsConfig?.defaultOpen !== false
|
|
8854
|
+
);
|
|
8855
|
+
const toggleSidebar = React.useCallback(() => setSidebarOpen((open) => !open), []);
|
|
8856
|
+
const effectiveConfig = React.useMemo(() => {
|
|
8857
|
+
if (!sessionsData.enabled) return config;
|
|
8858
|
+
return {
|
|
8859
|
+
...config,
|
|
8860
|
+
initialSessionId: sessionsData.activeSessionId,
|
|
8861
|
+
initialMessages: sessionsData.selectedMessages,
|
|
8862
|
+
autoGenerateSessionId: false,
|
|
8863
|
+
// Scope the message store per active session. The base userId alone
|
|
8864
|
+
// is shared across every session, so its chatStore entry would leak
|
|
8865
|
+
// the previous chat's messages into a newly-selected or brand-new
|
|
8866
|
+
// session (getStoredOrInitialMessages prefers the store over
|
|
8867
|
+
// initialMessages). Per-session keys give each chat a clean slate.
|
|
8868
|
+
userId: config.userId ? `${config.userId}::${sessionsData.activeSessionId}` : void 0
|
|
8869
|
+
};
|
|
8870
|
+
}, [
|
|
8871
|
+
config,
|
|
8872
|
+
sessionsData.enabled,
|
|
8873
|
+
sessionsData.activeSessionId,
|
|
8874
|
+
sessionsData.selectedMessages
|
|
8875
|
+
]);
|
|
8876
|
+
const sessionsPanel = React.useMemo(() => {
|
|
8877
|
+
if (!sessionsData.enabled) return void 0;
|
|
8878
|
+
return {
|
|
8879
|
+
open: sidebarOpen,
|
|
8880
|
+
onToggle: toggleSidebar,
|
|
8881
|
+
title: sessionsConfig?.title ?? "Chats",
|
|
8882
|
+
newChatLabel: sessionsConfig?.newChatLabel ?? "Start New Chat",
|
|
8883
|
+
sessionsList: sessionsData.sessionsList,
|
|
8884
|
+
isLoadingList: sessionsData.isLoadingList,
|
|
8885
|
+
listError: sessionsData.listError,
|
|
8886
|
+
activeSessionId: sessionsData.activeSessionId,
|
|
8887
|
+
onSelectSession: sessionsData.selectSession,
|
|
8888
|
+
onNewSession: sessionsData.startNewSession,
|
|
8889
|
+
actions: sessionsConfig?.actions,
|
|
8890
|
+
refetch: sessionsData.refetch,
|
|
8891
|
+
hasMore: sessionsData.hasMore,
|
|
8892
|
+
isLoadingMore: sessionsData.isLoadingMore,
|
|
8893
|
+
onLoadMore: sessionsData.loadMore,
|
|
8894
|
+
isLoadingMessages: sessionsData.isLoadingMessages
|
|
8895
|
+
};
|
|
8896
|
+
}, [
|
|
8897
|
+
sessionsData.enabled,
|
|
8898
|
+
sessionsData.sessionsList,
|
|
8899
|
+
sessionsData.isLoadingList,
|
|
8900
|
+
sessionsData.listError,
|
|
8901
|
+
sessionsData.activeSessionId,
|
|
8902
|
+
sessionsData.selectSession,
|
|
8903
|
+
sessionsData.startNewSession,
|
|
8904
|
+
sessionsData.refetch,
|
|
8905
|
+
sessionsData.hasMore,
|
|
8906
|
+
sessionsData.isLoadingMore,
|
|
8907
|
+
sessionsData.loadMore,
|
|
8908
|
+
sessionsData.isLoadingMessages,
|
|
8909
|
+
sidebarOpen,
|
|
8910
|
+
toggleSidebar,
|
|
8911
|
+
sessionsConfig?.title,
|
|
8912
|
+
sessionsConfig?.newChatLabel,
|
|
8913
|
+
sessionsConfig?.actions
|
|
8914
|
+
]);
|
|
8915
|
+
const callbacksWithSessionsRefresh = React.useMemo(() => {
|
|
8916
|
+
if (!sessionsData.enabled) return props.callbacks;
|
|
8917
|
+
return {
|
|
8918
|
+
...props.callbacks,
|
|
8919
|
+
// Reflect the message in the sidebar the instant it's sent, before
|
|
8920
|
+
// the server round-trip — the refetch below reconciles on complete.
|
|
8921
|
+
onMessageSent: (message) => {
|
|
8922
|
+
props.callbacks?.onMessageSent?.(message);
|
|
8923
|
+
sessionsData.noteSentMessage(message);
|
|
8924
|
+
},
|
|
8925
|
+
onStreamComplete: (message) => {
|
|
8926
|
+
props.callbacks?.onStreamComplete?.(message);
|
|
8927
|
+
sessionsData.refetch();
|
|
8928
|
+
}
|
|
8929
|
+
};
|
|
8930
|
+
}, [sessionsData.enabled, props.callbacks, sessionsData.refetch, sessionsData.noteSentMessage]);
|
|
8931
|
+
const availabilityPending = availabilityData.enabled && availabilityData.isLoading && availabilityData.available === null;
|
|
8932
|
+
if (availabilityPending) {
|
|
8933
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8934
|
+
"div",
|
|
8935
|
+
{
|
|
8936
|
+
className: cn("bg-background overflow-hidden flex flex-col flex-[4]", props.className),
|
|
8937
|
+
style: props.style,
|
|
8938
|
+
children: [
|
|
8939
|
+
props.children,
|
|
8940
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-chat-loading", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-spinner" }) })
|
|
8941
|
+
]
|
|
8942
|
+
}
|
|
8943
|
+
);
|
|
8944
|
+
}
|
|
8945
|
+
if (agentUnavailable) {
|
|
8946
|
+
const disabledBody = availabilityStatus === "blocked" ? config.availability?.blockedComponent ?? /* @__PURE__ */ jsxRuntime.jsx(AvailabilityNotice, { message: DEFAULT_USER_BLOCKED_MESSAGE }) : config.availability?.disabledComponent ?? /* @__PURE__ */ jsxRuntime.jsx(AvailabilityNotice, { message: DEFAULT_AGENT_DISABLED_MESSAGE });
|
|
8947
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8948
|
+
"div",
|
|
8949
|
+
{
|
|
8950
|
+
className: cn("bg-background overflow-hidden flex flex-col flex-[4]", props.className),
|
|
8951
|
+
style: props.style,
|
|
8952
|
+
children: [
|
|
8953
|
+
props.children,
|
|
8954
|
+
disabledBody
|
|
8955
|
+
]
|
|
8956
|
+
}
|
|
8957
|
+
);
|
|
8958
|
+
}
|
|
8959
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8960
|
+
PaymanChatWithChat,
|
|
8961
|
+
{
|
|
8962
|
+
...props,
|
|
8963
|
+
config: effectiveConfig,
|
|
8964
|
+
callbacks: callbacksWithSessionsRefresh,
|
|
8965
|
+
sessionsPanel,
|
|
8966
|
+
ref
|
|
8967
|
+
},
|
|
8968
|
+
sessionsData.enabled ? sessionsData.activeSessionId : void 0
|
|
8969
|
+
);
|
|
8970
|
+
}
|
|
8971
|
+
);
|
|
6897
8972
|
|
|
6898
8973
|
exports.PaymanChat = PaymanChat;
|
|
6899
8974
|
exports.PaymanChatContext = PaymanChatContext;
|
|
@@ -6904,6 +8979,7 @@ exports.cn = cn;
|
|
|
6904
8979
|
exports.formatDate = formatDate;
|
|
6905
8980
|
exports.resendUserAction = resendUserAction;
|
|
6906
8981
|
exports.submitUserAction = submitUserAction;
|
|
8982
|
+
exports.useAgentConfig = useAgentConfig;
|
|
6907
8983
|
exports.useChatV2 = useChatV2;
|
|
6908
8984
|
exports.usePaymanChat = usePaymanChat;
|
|
6909
8985
|
exports.useVoice = useVoice;
|