mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-29 19:35:20 +02:00
feat(web): enhance composer suggestion skeleton, improve document mention picker loading states & improved LLM prompt block for connector mentions
This commit is contained in:
parent
17293125ef
commit
dbf235cbda
4 changed files with 31 additions and 16 deletions
|
|
@ -1401,14 +1401,15 @@ async def stream_new_chat(
|
||||||
continue
|
continue
|
||||||
connector_lines.append(
|
connector_lines.append(
|
||||||
f' - connector_id={connector_id}, connector_type="{connector_type}", '
|
f' - connector_id={connector_id}, connector_type="{connector_type}", '
|
||||||
f'account="{account_name or ""}"'
|
f'account_name="{account_name or ""}"'
|
||||||
)
|
)
|
||||||
if connector_lines:
|
if connector_lines:
|
||||||
context_parts.append(
|
context_parts.append(
|
||||||
"<mentioned_connectors>\n"
|
"<mentioned_connectors>\n"
|
||||||
"The user selected these exact connector accounts with @. "
|
"The user selected these exact connector accounts with @. "
|
||||||
"For read, write, or HITL tool calls involving these services, "
|
"These entries are selection metadata, not retrieved connector content. "
|
||||||
"prefer the matching connector_id instead of guessing from available accounts:\n"
|
"When a connector-backed tool needs an account, use the matching "
|
||||||
|
"connector_id from this list if the tool supports connector_id:\n"
|
||||||
+ "\n".join(connector_lines)
|
+ "\n".join(connector_lines)
|
||||||
+ "\n</mentioned_connectors>"
|
+ "\n</mentioned_connectors>"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ function ComposerSuggestionPopoverContent({
|
||||||
onCloseAutoFocus?.(event);
|
onCloseAutoFocus?.(event);
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-[232px] overflow-hidden rounded-md border border-popover-border bg-popover p-0 text-popover-foreground shadow-md sm:w-[264px]",
|
"w-[232px] select-none overflow-hidden rounded-md border border-popover-border bg-popover p-0 text-popover-foreground shadow-md sm:w-[264px]",
|
||||||
"data-[state=open]:!animate-none data-[state=closed]:!animate-none data-[state=open]:!duration-0 data-[state=closed]:!duration-0",
|
"data-[state=open]:!animate-none data-[state=closed]:!animate-none data-[state=open]:!duration-0 data-[state=closed]:!duration-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
|
@ -145,18 +145,24 @@ function ComposerSuggestionMessage({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ComposerSuggestionSkeleton() {
|
function ComposerSuggestionSkeleton({
|
||||||
|
rows = 5,
|
||||||
|
mobileRows = 3,
|
||||||
|
}: {
|
||||||
|
rows?: number;
|
||||||
|
mobileRows?: number;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="px-1.5 py-1">
|
<div className="px-1.5 py-1">
|
||||||
<div className="px-2 py-1">
|
<div className="px-2 py-1">
|
||||||
<Skeleton className="h-3.5 w-20" />
|
<Skeleton className="h-3.5 w-20" />
|
||||||
</div>
|
</div>
|
||||||
{["a", "b", "c", "d", "e"].map((id, index) => (
|
{Array.from({ length: rows }, (_, index) => `skeleton-row-${index}`).map((id, index) => (
|
||||||
<div
|
<div
|
||||||
key={id}
|
key={id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full items-center gap-1.5 rounded-md px-2 py-1 text-left",
|
"flex w-full items-center gap-1.5 rounded-md px-2 py-1 text-left",
|
||||||
index >= 3 && "hidden sm:flex"
|
index >= mobileRows && "hidden sm:flex"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="shrink-0">
|
<span className="shrink-0">
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ export const DocumentMentionPicker = forwardRef<
|
||||||
() => new Set(initialSelectedDocuments.map((d) => getMentionDocKey(d))),
|
() => new Set(initialSelectedDocuments.map((d) => getMentionDocKey(d))),
|
||||||
[initialSelectedDocuments]
|
[initialSelectedDocuments]
|
||||||
);
|
);
|
||||||
const showSurfsenseDocsRootRef = useRef((surfsenseDocs?.items?.length ?? 0) > 0);
|
const showSurfsenseDocsRoot = surfsenseDocsList.length > 0;
|
||||||
|
|
||||||
const selectMention = useCallback(
|
const selectMention = useCallback(
|
||||||
(mention: MentionedDocumentInfo) => {
|
(mention: MentionedDocumentInfo) => {
|
||||||
|
|
@ -463,7 +463,7 @@ export const DocumentMentionPicker = forwardRef<
|
||||||
const rootNodes = useMemo<ComposerSuggestionNode<ResourceNodeValue>[]>(
|
const rootNodes = useMemo<ComposerSuggestionNode<ResourceNodeValue>[]>(
|
||||||
() => {
|
() => {
|
||||||
const nodes: ComposerSuggestionNode<ResourceNodeValue>[] = [...recentRootNodes];
|
const nodes: ComposerSuggestionNode<ResourceNodeValue>[] = [...recentRootNodes];
|
||||||
if (showSurfsenseDocsRootRef.current) {
|
if (showSurfsenseDocsRoot) {
|
||||||
nodes.push({
|
nodes.push({
|
||||||
id: "surfsense-docs",
|
id: "surfsense-docs",
|
||||||
label: "SurfSense Docs",
|
label: "SurfSense Docs",
|
||||||
|
|
@ -496,7 +496,7 @@ export const DocumentMentionPicker = forwardRef<
|
||||||
);
|
);
|
||||||
return nodes;
|
return nodes;
|
||||||
},
|
},
|
||||||
[activeConnectors.length, recentRootNodes]
|
[activeConnectors.length, recentRootNodes, showSurfsenseDocsRoot]
|
||||||
);
|
);
|
||||||
|
|
||||||
const searchNodes = useMemo<ComposerSuggestionNode<ResourceNodeValue>[]>(() => {
|
const searchNodes = useMemo<ComposerSuggestionNode<ResourceNodeValue>[]>(() => {
|
||||||
|
|
@ -680,11 +680,18 @@ export const DocumentMentionPicker = forwardRef<
|
||||||
[canLoadMoreDocuments, hasMore, isLoadingMore, loadNextPage]
|
[canLoadMoreDocuments, hasMore, isLoadingMore, loadNextPage]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isRootBrowseView = !hasSearch && view.kind === "root";
|
||||||
|
const isVisibleViewLoading = hasSearch
|
||||||
|
? isTitleSearchLoading || isSurfsenseDocsLoading || isConnectorsLoading
|
||||||
|
: view.kind === "surfsense-docs"
|
||||||
|
? isSurfsenseDocsLoading
|
||||||
|
: view.kind === "files-folders"
|
||||||
|
? isTitleSearchLoading
|
||||||
|
: view.kind === "connectors" || view.kind === "connector-type"
|
||||||
|
? isConnectorsLoading
|
||||||
|
: false;
|
||||||
const actualLoading =
|
const actualLoading =
|
||||||
(isTitleSearchLoading || isSurfsenseDocsLoading || isConnectorsLoading) &&
|
isVisibleViewLoading && !isSingleCharSearch && visibleNodes.length === 0 && !isRootBrowseView;
|
||||||
!isSingleCharSearch &&
|
|
||||||
visibleNodes.length === 0 &&
|
|
||||||
(view.kind === "root" || hasSearch);
|
|
||||||
|
|
||||||
const title =
|
const title =
|
||||||
hasSearch || view.kind === "root"
|
hasSearch || view.kind === "root"
|
||||||
|
|
@ -703,9 +710,10 @@ export const DocumentMentionPicker = forwardRef<
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
role="listbox"
|
role="listbox"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
|
className={isRootBrowseView ? "max-h-none overflow-visible sm:max-h-none" : undefined}
|
||||||
>
|
>
|
||||||
{actualLoading ? (
|
{actualLoading ? (
|
||||||
<ComposerSuggestionSkeleton />
|
<ComposerSuggestionSkeleton rows={8} mobileRows={8} />
|
||||||
) : (
|
) : (
|
||||||
<ComposerSuggestionGroup>
|
<ComposerSuggestionGroup>
|
||||||
{title ? (
|
{title ? (
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ export const PromptPicker = forwardRef<PromptPickerRef, PromptPickerProps>(funct
|
||||||
return (
|
return (
|
||||||
<ComposerSuggestionList ref={scrollContainerRef}>
|
<ComposerSuggestionList ref={scrollContainerRef}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<ComposerSuggestionSkeleton />
|
<ComposerSuggestionSkeleton rows={8} mobileRows={8} />
|
||||||
) : isError ? (
|
) : isError ? (
|
||||||
<ComposerSuggestionMessage variant="destructive">Failed to load prompts</ComposerSuggestionMessage>
|
<ComposerSuggestionMessage variant="destructive">Failed to load prompts</ComposerSuggestionMessage>
|
||||||
) : filtered.length === 0 ? (
|
) : filtered.length === 0 ? (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue