@paymanai/payman-ask-sdk 4.0.27 → 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 +18 -10
- package/dist/index.d.ts +18 -10
- package/dist/index.js +1337 -182
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1338 -184
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +2 -1
- package/dist/index.native.js.map +1 -1
- package/dist/styles.css +613 -1
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1821,6 +1821,284 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1821
1821
|
reset
|
|
1822
1822
|
};
|
|
1823
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
|
+
}
|
|
1824
2102
|
function classifyField(field) {
|
|
1825
2103
|
if (!field) return "text";
|
|
1826
2104
|
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
@@ -3277,11 +3555,10 @@ function UserMessageV2({
|
|
|
3277
3555
|
),
|
|
3278
3556
|
style: { borderRadius: 9999 },
|
|
3279
3557
|
children: [
|
|
3280
|
-
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(
|
|
3281
3559
|
lucideReact.AlertCircle,
|
|
3282
3560
|
{
|
|
3283
|
-
|
|
3284
|
-
style: { color: "#ef4444" }
|
|
3561
|
+
style: { width: 14, height: 14, color: "#ef4444" }
|
|
3285
3562
|
}
|
|
3286
3563
|
),
|
|
3287
3564
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: toast.label })
|
|
@@ -3305,8 +3582,13 @@ function UserMessageV2({
|
|
|
3305
3582
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3306
3583
|
lucideReact.AlertCircle,
|
|
3307
3584
|
{
|
|
3308
|
-
|
|
3309
|
-
|
|
3585
|
+
style: {
|
|
3586
|
+
width: 14,
|
|
3587
|
+
height: 14,
|
|
3588
|
+
flexShrink: 0,
|
|
3589
|
+
color: "rgba(239, 68, 68, 0.7)",
|
|
3590
|
+
marginTop: "2px"
|
|
3591
|
+
}
|
|
3310
3592
|
}
|
|
3311
3593
|
),
|
|
3312
3594
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-user-msg-error-text", children: resolvedError })
|
|
@@ -3324,10 +3606,9 @@ function UserMessageV2({
|
|
|
3324
3606
|
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3325
3607
|
lucideReact.Check,
|
|
3326
3608
|
{
|
|
3327
|
-
|
|
3328
|
-
style: { color: "#059669" }
|
|
3609
|
+
style: { width: 14, height: 14, color: "#059669" }
|
|
3329
3610
|
}
|
|
3330
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, {
|
|
3611
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { style: { width: 14, height: 14 } })
|
|
3331
3612
|
}
|
|
3332
3613
|
) }),
|
|
3333
3614
|
showEditAction && onEdit && /* @__PURE__ */ jsxRuntime.jsx(ActionTooltipV2, { label: "Edit", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3337,7 +3618,7 @@ function UserMessageV2({
|
|
|
3337
3618
|
onClick: () => onEdit(message.id),
|
|
3338
3619
|
className: "payman-v2-user-msg-action-btn",
|
|
3339
3620
|
"aria-label": "Edit message",
|
|
3340
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, {
|
|
3621
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { style: { width: 14, height: 14 } })
|
|
3341
3622
|
}
|
|
3342
3623
|
) }),
|
|
3343
3624
|
showRetryAction && onRetry && /* @__PURE__ */ jsxRuntime.jsx(ActionTooltipV2, { label: "Retry", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3348,7 +3629,7 @@ function UserMessageV2({
|
|
|
3348
3629
|
disabled: retryDisabled,
|
|
3349
3630
|
className: "payman-v2-user-msg-action-btn",
|
|
3350
3631
|
"aria-label": "Retry message",
|
|
3351
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, {
|
|
3632
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { style: { width: 14, height: 14 } })
|
|
3352
3633
|
}
|
|
3353
3634
|
) })
|
|
3354
3635
|
] })
|
|
@@ -4262,14 +4543,12 @@ function AssistantMessageV2({
|
|
|
4262
4543
|
toast.tone === "success" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4263
4544
|
lucideReact.Check,
|
|
4264
4545
|
{
|
|
4265
|
-
|
|
4266
|
-
style: { color: "#059669" }
|
|
4546
|
+
style: { width: 14, height: 14, color: "#059669" }
|
|
4267
4547
|
}
|
|
4268
4548
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4269
4549
|
lucideReact.AlertCircle,
|
|
4270
4550
|
{
|
|
4271
|
-
|
|
4272
|
-
style: { color: "#ef4444" }
|
|
4551
|
+
style: { width: 14, height: 14, color: "#ef4444" }
|
|
4273
4552
|
}
|
|
4274
4553
|
),
|
|
4275
4554
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: toast.label })
|
|
@@ -5619,6 +5898,62 @@ var MessageListV2 = React.forwardRef(
|
|
|
5619
5898
|
] });
|
|
5620
5899
|
}
|
|
5621
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
|
+
}
|
|
5622
5957
|
var ChatInputV2 = React.forwardRef(
|
|
5623
5958
|
function ChatInputV22({
|
|
5624
5959
|
onSend,
|
|
@@ -6009,12 +6344,7 @@ var ChatInputV2 = React.forwardRef(
|
|
|
6009
6344
|
showActions && "payman-v2-input-attach-btn-active"
|
|
6010
6345
|
),
|
|
6011
6346
|
"aria-label": "Attach",
|
|
6012
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6013
|
-
lucideReact.Plus,
|
|
6014
|
-
{
|
|
6015
|
-
style: { width: 20, height: 20, strokeWidth: 2 }
|
|
6016
|
-
}
|
|
6017
|
-
)
|
|
6347
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(IconPlus, { size: 20 })
|
|
6018
6348
|
}
|
|
6019
6349
|
),
|
|
6020
6350
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showActions && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6097,7 +6427,7 @@ var ChatInputV2 = React.forwardRef(
|
|
|
6097
6427
|
),
|
|
6098
6428
|
"aria-label": isRecording ? "Stop recording" : "Voice input",
|
|
6099
6429
|
children: [
|
|
6100
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6430
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconMic, { size: 18 }),
|
|
6101
6431
|
isRecording && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-input-mic-indicator" })
|
|
6102
6432
|
]
|
|
6103
6433
|
}
|
|
@@ -7160,6 +7490,584 @@ function TimelineBars({
|
|
|
7160
7490
|
)
|
|
7161
7491
|
] });
|
|
7162
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
|
+
]
|
|
7968
|
+
}
|
|
7969
|
+
),
|
|
7970
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-sessions-divider" }),
|
|
7971
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7972
|
+
SessionsListBody,
|
|
7973
|
+
{
|
|
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
|
|
7985
|
+
}
|
|
7986
|
+
)
|
|
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
|
+
),
|
|
8020
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8021
|
+
framerMotion.motion.div,
|
|
8022
|
+
{
|
|
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 },
|
|
8031
|
+
children: [
|
|
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
|
+
)
|
|
8045
|
+
] }),
|
|
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
|
+
)
|
|
8066
|
+
]
|
|
8067
|
+
}
|
|
8068
|
+
)
|
|
8069
|
+
] });
|
|
8070
|
+
}
|
|
7163
8071
|
var DEFAULT_USER_ACTION_STATE = {
|
|
7164
8072
|
prompts: [],
|
|
7165
8073
|
notifications: []
|
|
@@ -7254,7 +8162,8 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7254
8162
|
onLoadMoreMessages,
|
|
7255
8163
|
isLoadingMoreMessages = false,
|
|
7256
8164
|
hasMoreMessages = false,
|
|
7257
|
-
chat
|
|
8165
|
+
chat,
|
|
8166
|
+
sessionsPanel
|
|
7258
8167
|
}, ref) {
|
|
7259
8168
|
const [inputValue, setInputValue] = React.useState("");
|
|
7260
8169
|
const prevInputValueRef = React.useRef(inputValue);
|
|
@@ -7267,6 +8176,25 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7267
8176
|
const chatInputV2Ref = React.useRef(null);
|
|
7268
8177
|
const messageListV2Ref = React.useRef(null);
|
|
7269
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]);
|
|
7270
8198
|
React.useEffect(() => {
|
|
7271
8199
|
if (config.sentryDsn) {
|
|
7272
8200
|
initSentryIfNeeded(config.sentryDsn);
|
|
@@ -7421,13 +8349,20 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7421
8349
|
if (isRecording) {
|
|
7422
8350
|
stopRecording();
|
|
7423
8351
|
}
|
|
7424
|
-
|
|
8352
|
+
if (sessionsPanel?.onNewSession) {
|
|
8353
|
+
sessionsPanel.onNewSession();
|
|
8354
|
+
if (isCompact && sessionsPanel.open) sessionsPanel.onToggle();
|
|
8355
|
+
} else {
|
|
8356
|
+
resetSession();
|
|
8357
|
+
}
|
|
7425
8358
|
onResetSession?.();
|
|
7426
8359
|
}, [
|
|
7427
8360
|
clearTranscript,
|
|
7428
8361
|
isRecording,
|
|
8362
|
+
isCompact,
|
|
7429
8363
|
onResetSession,
|
|
7430
8364
|
resetSession,
|
|
8365
|
+
sessionsPanel,
|
|
7431
8366
|
stopRecording
|
|
7432
8367
|
]);
|
|
7433
8368
|
const requestResetSession = React.useCallback(() => {
|
|
@@ -7441,8 +8376,9 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7441
8376
|
clearMessages,
|
|
7442
8377
|
cancelStream,
|
|
7443
8378
|
getSessionId,
|
|
7444
|
-
getMessages
|
|
7445
|
-
|
|
8379
|
+
getMessages,
|
|
8380
|
+
refreshSessions: sessionsPanel?.refetch ?? NOOP
|
|
8381
|
+
}), [performResetSession, clearMessages, cancelStream, getSessionId, getMessages, sessionsPanel?.refetch]);
|
|
7446
8382
|
const {
|
|
7447
8383
|
placeholder = "Type your message...",
|
|
7448
8384
|
emptyStateText = "What can I help with?",
|
|
@@ -7562,9 +8498,13 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7562
8498
|
};
|
|
7563
8499
|
const userActionPrompts = isUserActionSupported ? userActionState.prompts : void 0;
|
|
7564
8500
|
const notifications = userActionState.notifications;
|
|
7565
|
-
const
|
|
8501
|
+
const dockableUserActionPrompts = userActionPrompts?.filter(
|
|
7566
8502
|
(prompt) => prompt.kind !== "notification" && (prompt.status === "pending" || prompt.status === "submitting" || prompt.status === "stale")
|
|
7567
8503
|
);
|
|
8504
|
+
const dockedPendingPrompts = dockableUserActionPrompts?.filter(
|
|
8505
|
+
(prompt) => prompt.status === "pending"
|
|
8506
|
+
);
|
|
8507
|
+
const dockedPrompt = dockedPendingPrompts?.[dockedPendingPrompts.length - 1] ?? dockableUserActionPrompts?.[dockableUserActionPrompts.length - 1];
|
|
7568
8508
|
const handleV2Send = (text) => {
|
|
7569
8509
|
if (isRecording) stopRecording();
|
|
7570
8510
|
if (text.trim() && !disableInput && isSessionParamsConfigured) {
|
|
@@ -7613,171 +8553,236 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7613
8553
|
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7614
8554
|
"div",
|
|
7615
8555
|
{
|
|
8556
|
+
ref: rootRef,
|
|
7616
8557
|
className: cn("payman-v2-root", className),
|
|
7617
8558
|
style,
|
|
7618
8559
|
children: [
|
|
7619
8560
|
children,
|
|
7620
|
-
/* @__PURE__ */ jsxRuntime.
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
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,
|
|
7665
8634
|
{
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
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
|
+
)
|
|
7691
8696
|
}
|
|
7692
8697
|
)
|
|
7693
|
-
}
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7707
|
-
MessageListV2,
|
|
7708
|
-
{
|
|
7709
|
-
ref: messageListV2Ref,
|
|
7710
|
-
messages,
|
|
7711
|
-
isStreaming: isWaitingForResponse,
|
|
7712
|
-
onEditUserMessage: handleEditMessageDraft,
|
|
7713
|
-
onRetryUserMessage: handleRetryUserMessage,
|
|
7714
|
-
onImageClick: handleImageClick,
|
|
7715
|
-
onExecutionTraceClick,
|
|
7716
|
-
messageActions,
|
|
7717
|
-
retryDisabled: isWaitingForResponse,
|
|
7718
|
-
typingSpeed: config.typingSpeed ?? 4,
|
|
7719
|
-
userActionPrompts,
|
|
7720
|
-
dockedUserActionId: dockedPrompt?.userActionId,
|
|
7721
|
-
notifications,
|
|
7722
|
-
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
7723
|
-
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
7724
|
-
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
7725
|
-
onExpireUserAction: isUserActionSupported ? async (id) => expireUserActionOnce(id) : void 0,
|
|
7726
|
-
onDismissNotification: dismissNotification,
|
|
7727
|
-
onSubmitFeedback: handleSubmitFeedback
|
|
7728
|
-
}
|
|
7729
|
-
),
|
|
7730
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7731
|
-
StreamingIndicatorV2,
|
|
7732
|
-
{
|
|
7733
|
-
isStreaming: isWaitingForResponse,
|
|
7734
|
-
loadingAnimation: config.loadingAnimation
|
|
7735
|
-
}
|
|
7736
|
-
),
|
|
7737
|
-
hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7738
|
-
UserActionDock,
|
|
7739
|
-
{
|
|
7740
|
-
prompt: isUserActionSupported ? dockedPrompt : void 0,
|
|
7741
|
-
onSubmit: submitUserAction2,
|
|
7742
|
-
onCancel: cancelUserAction2,
|
|
7743
|
-
onResend: resendUserAction2,
|
|
7744
|
-
onExpired: expireUserActionOnce,
|
|
7745
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7746
|
-
ChatInputV2,
|
|
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,
|
|
7747
8711
|
{
|
|
7748
|
-
ref:
|
|
7749
|
-
|
|
7750
|
-
onCancel: cancelStream,
|
|
7751
|
-
disabled: isV2InputDisabled,
|
|
8712
|
+
ref: messageListV2Ref,
|
|
8713
|
+
messages,
|
|
7752
8714
|
isStreaming: isWaitingForResponse,
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
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,
|
|
8735
|
+
{
|
|
8736
|
+
isStreaming: isWaitingForResponse,
|
|
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
|
+
)
|
|
7773
8778
|
}
|
|
7774
8779
|
)
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
8780
|
+
]
|
|
8781
|
+
},
|
|
8782
|
+
"v2-chat"
|
|
8783
|
+
) })
|
|
8784
|
+
] })
|
|
8785
|
+
] }),
|
|
7781
8786
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7782
8787
|
ImageLightboxV2,
|
|
7783
8788
|
{
|
|
@@ -7808,13 +8813,162 @@ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
|
7808
8813
|
}
|
|
7809
8814
|
) });
|
|
7810
8815
|
});
|
|
7811
|
-
var
|
|
7812
|
-
function
|
|
8816
|
+
var PaymanChatWithChat = React.forwardRef(
|
|
8817
|
+
function PaymanChatWithChat2(props, ref) {
|
|
7813
8818
|
const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
|
|
7814
8819
|
const chat = useChatV2(props.config, mergedCallbacks);
|
|
7815
8820
|
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatInner, { ...props, chat, ref });
|
|
7816
8821
|
}
|
|
7817
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
|
+
);
|
|
7818
8972
|
|
|
7819
8973
|
exports.PaymanChat = PaymanChat;
|
|
7820
8974
|
exports.PaymanChatContext = PaymanChatContext;
|
|
@@ -7825,6 +8979,7 @@ exports.cn = cn;
|
|
|
7825
8979
|
exports.formatDate = formatDate;
|
|
7826
8980
|
exports.resendUserAction = resendUserAction;
|
|
7827
8981
|
exports.submitUserAction = submitUserAction;
|
|
8982
|
+
exports.useAgentConfig = useAgentConfig;
|
|
7828
8983
|
exports.useChatV2 = useChatV2;
|
|
7829
8984
|
exports.usePaymanChat = usePaymanChat;
|
|
7830
8985
|
exports.useVoice = useVoice;
|