Skip to content

Commit 9b00c45

Browse files
committed
enable all by default and persist user choice
1 parent 7eeab8f commit 9b00c45

File tree

3 files changed

+239
-9
lines changed

3 files changed

+239
-9
lines changed

backend/onyx/federated_connectors/federated_retrieval.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,16 @@ def get_federated_retrieval_functions(
135135
# At this point, user_id is guaranteed to be not None since we're in the else branch
136136
assert user_id is not None
137137

138+
# If no source types are specified, don't use any federated connectors
139+
if source_types is None:
140+
logger.info("No source types specified, skipping all federated connectors")
141+
return []
142+
138143
federated_retrieval_infos: list[FederatedRetrievalInfo] = []
139144
federated_oauth_tokens = list_federated_connector_oauth_tokens(db_session, user_id)
140145
for oauth_token in federated_oauth_tokens:
141146
if (
142-
source_types is not None
143-
and oauth_token.federated_connector.source.to_non_federated_source()
147+
oauth_token.federated_connector.source.to_non_federated_source()
144148
not in source_types
145149
):
146150
continue

web/src/app/chat/components/input/ActionManagement.tsx

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { useAssistantsContext } from "@/components/context/AssistantsContext";
2525
import Link from "next/link";
2626
import { getIconForAction } from "../../services/actionUtils";
2727
import { useUser } from "@/components/user/UserProvider";
28-
import { useFilters } from "@/lib/hooks";
28+
import { useFilters, FilterManager } from "@/lib/hooks";
2929
import { listSourceMetadata } from "@/lib/sources";
3030
import {
3131
FiServer,
@@ -433,11 +433,13 @@ function MCPToolsList({
433433
interface ActionToggleProps {
434434
selectedAssistant: MinimalPersonaSnapshot;
435435
availableSources?: ValidSources[];
436+
filterManager: FilterManager;
436437
}
437438

438439
export function ActionToggle({
439440
selectedAssistant,
440441
availableSources = [],
442+
filterManager,
441443
}: ActionToggleProps) {
442444
const { theme } = useTheme();
443445
const [open, setOpen] = useState(false);
@@ -446,10 +448,49 @@ export function ActionToggle({
446448
const [sourceSearchTerm, setSourceSearchTerm] = useState("");
447449
const [showFadeMask, setShowFadeMask] = useState(false);
448450
const [showTopShadow, setShowTopShadow] = useState(false);
449-
// Use existing filter system
450-
const filterManager = useFilters();
451451
const { selectedSources, setSelectedSources } = filterManager;
452452
const [mcpServers, setMcpServers] = useState<MCPServer[]>([]);
453+
const [sourcesInitialized, setSourcesInitialized] = useState(false);
454+
455+
// Load saved source preferences from localStorage
456+
const loadSavedSourcePreferences = () => {
457+
if (typeof window === "undefined") return null;
458+
const saved = localStorage.getItem("chat-selected-sources");
459+
if (!saved) return null;
460+
try {
461+
return JSON.parse(saved);
462+
} catch {
463+
return null;
464+
}
465+
};
466+
467+
const persistSourcePreferencesState = (sources: SourceMetadata[]) => {
468+
if (typeof window === "undefined") return;
469+
localStorage.setItem("chat-selected-sources", JSON.stringify(sources));
470+
};
471+
472+
// Initialize sources - load from localStorage or enable all by default
473+
useEffect(() => {
474+
if (!sourcesInitialized && availableSources.length > 0) {
475+
const savedSources = loadSavedSourcePreferences();
476+
if (savedSources !== null) {
477+
const availableSourceMetadata = getConfiguredSources(availableSources);
478+
const validSavedSources = savedSources.filter(
479+
(savedSource: SourceMetadata) =>
480+
availableSourceMetadata.some(
481+
(availableSource) =>
482+
availableSource.uniqueKey === savedSource.uniqueKey
483+
)
484+
);
485+
setSelectedSources(validSavedSources);
486+
} else {
487+
// First time user - enable all sources by default
488+
const allSourceMetadata = getConfiguredSources(availableSources);
489+
setSelectedSources(allSourceMetadata);
490+
}
491+
setSourcesInitialized(true);
492+
}
493+
}, [availableSources, sourcesInitialized, setSelectedSources]);
453494
const [mcpToolsPopup, setMcpToolsPopup] = useState<{
454495
serverId: number | null;
455496
serverName: string;
@@ -525,10 +566,12 @@ export function ActionToggle({
525566
const enableAllSources = () => {
526567
const allSourceMetadata = getConfiguredSources(availableSources);
527568
setSelectedSources(allSourceMetadata);
569+
persistSourcePreferencesState(allSourceMetadata);
528570
};
529571

530572
const disableAllSources = () => {
531573
setSelectedSources([]);
574+
persistSourcePreferencesState([]);
532575
};
533576

534577
const toggleSource = (sourceUniqueKey: string) => {
@@ -541,13 +584,17 @@ export function ActionToggle({
541584
(s) => s.uniqueKey === configuredSource.uniqueKey
542585
);
543586

587+
let newSources: SourceMetadata[];
544588
if (isCurrentlySelected) {
545-
setSelectedSources((prev) =>
546-
prev.filter((s) => s.uniqueKey !== configuredSource.uniqueKey)
589+
newSources = selectedSources.filter(
590+
(s) => s.uniqueKey !== configuredSource.uniqueKey
547591
);
548592
} else {
549-
setSelectedSources((prev) => [...prev, configuredSource]);
593+
newSources = [...selectedSources, configuredSource];
550594
}
595+
596+
setSelectedSources(newSources);
597+
persistSourcePreferencesState(newSources);
551598
};
552599

553600
const isSourceEnabled = (sourceUniqueKey: string) => {
@@ -556,7 +603,7 @@ export function ActionToggle({
556603
);
557604
if (!configuredSource) return false;
558605
return selectedSources.some(
559-
(s) => s.uniqueKey === configuredSource.uniqueKey
606+
(s: SourceMetadata) => s.uniqueKey === configuredSource.uniqueKey
560607
);
561608
};
562609

web/src/app/chat/components/input/ChatInputBar.tsx

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ export const ChatInputBar = React.memo(function ChatInputBar({
503503
suppressContentEditableWarning={true}
504504
/>
505505

506+
<<<<<<< HEAD
506507
{(selectedDocuments.length > 0 ||
507508
currentMessageFiles.length > 0 ||
508509
filterManager.timeRange ||
@@ -523,6 +524,184 @@ export const ChatInputBar = React.memo(function ChatInputBar({
523524
(t) => t.tag_key !== tag.tag_key
524525
)
525526
);
527+
=======
528+
{(selectedDocuments.length > 0 ||
529+
selectedFiles.length > 0 ||
530+
selectedFolders.length > 0 ||
531+
currentMessageFiles.length > 0 ||
532+
filterManager.timeRange ||
533+
filterManager.selectedDocumentSets.length > 0 ||
534+
filterManager.selectedTags.length > 0) && (
535+
<div className="flex bg-input-background gap-x-.5 px-2">
536+
<div className="flex gap-x-1 px-2 overflow-visible overflow-x-scroll items-end miniscroll">
537+
{filterManager.selectedTags &&
538+
filterManager.selectedTags.map((tag, index) => (
539+
<SourceChip
540+
key={index}
541+
icon={<TagIcon size={12} />}
542+
title={`#${tag.tag_key}_${tag.tag_value}`}
543+
onRemove={() => {
544+
filterManager.setSelectedTags(
545+
filterManager.selectedTags.filter(
546+
(t) => t.tag_key !== tag.tag_key
547+
)
548+
);
549+
}}
550+
/>
551+
))}
552+
553+
{/* Unified file rendering section for both selected and current message files */}
554+
{allFiles.map((file, index) =>
555+
file.chatFileType === ChatFileType.IMAGE ? (
556+
<SourceChip
557+
key={`${file.source}-${file.id}-${index}`}
558+
icon={
559+
file.isUploading ? (
560+
<FiLoader className="animate-spin" />
561+
) : (
562+
<img
563+
className="h-full py-.5 object-cover rounded-lg bg-background cursor-pointer"
564+
src={buildImgUrl(file.id)}
565+
alt={file.name || "File image"}
566+
/>
567+
)
568+
}
569+
title={file.name}
570+
onRemove={() => {
571+
if (file.source === "selected") {
572+
removeSelectedFile(file.originalFile);
573+
} else {
574+
setCurrentMessageFiles(
575+
currentMessageFiles.filter(
576+
(fileInFilter) => fileInFilter.id !== file.id
577+
)
578+
);
579+
}
580+
}}
581+
/>
582+
) : (
583+
<SourceChip
584+
key={`${file.source}-${file.id}-${index}`}
585+
icon={
586+
<FileIcon
587+
className={
588+
file.source === "current" ? "text-red-500" : ""
589+
}
590+
size={16}
591+
/>
592+
}
593+
title={file.name}
594+
onRemove={() => {
595+
if (file.source === "selected") {
596+
removeSelectedFile(file.originalFile);
597+
} else {
598+
setCurrentMessageFiles(
599+
currentMessageFiles.filter(
600+
(fileInFilter) => fileInFilter.id !== file.id
601+
)
602+
);
603+
}
604+
}}
605+
/>
606+
)
607+
)}
608+
{selectedFolders.map((folder) => (
609+
<SourceChip
610+
key={folder.id}
611+
icon={<FolderIcon size={16} />}
612+
title={folder.name}
613+
onRemove={() => removeSelectedFolder(folder)}
614+
/>
615+
))}
616+
{filterManager.timeRange && (
617+
<SourceChip
618+
truncateTitle={false}
619+
key="time-range"
620+
icon={<CalendarIcon size={12} />}
621+
title={`${getFormattedDateRangeString(
622+
filterManager.timeRange.from,
623+
filterManager.timeRange.to
624+
)}`}
625+
onRemove={() => {
626+
filterManager.setTimeRange(null);
627+
}}
628+
/>
629+
)}
630+
{filterManager.selectedDocumentSets.length > 0 &&
631+
filterManager.selectedDocumentSets.map((docSet, index) => (
632+
<SourceChip
633+
key={`doc-set-${index}`}
634+
icon={<DocumentIcon2 size={16} />}
635+
title={docSet}
636+
onRemove={() => {
637+
filterManager.setSelectedDocumentSets(
638+
filterManager.selectedDocumentSets.filter(
639+
(ds) => ds !== docSet
640+
)
641+
);
642+
}}
643+
/>
644+
))}
645+
{selectedDocuments.length > 0 && (
646+
<SourceChip
647+
key="selected-documents"
648+
onClick={() => {
649+
toggleDocumentSidebar();
650+
}}
651+
icon={<FileIcon size={16} />}
652+
title={`${selectedDocuments.length} selected`}
653+
onRemove={removeDocs}
654+
/>
655+
)}
656+
</div>
657+
</div>
658+
)}
659+
660+
<div className="flex pr-4 pb-2 justify-between bg-input-background items-center w-full ">
661+
<div className="space-x-1 flex px-4 ">
662+
<ChatInputOption
663+
flexPriority="stiff"
664+
Icon={FileUploadIcon}
665+
onClick={() => {
666+
toggleDocSelection();
667+
}}
668+
tooltipContent={"Upload files and attach user files"}
669+
/>
670+
671+
{selectedAssistant.tools.length > 0 && (
672+
<ActionToggle
673+
selectedAssistant={selectedAssistant}
674+
availableSources={memoizedAvailableSources}
675+
filterManager={filterManager}
676+
/>
677+
)}
678+
679+
{retrievalEnabled &&
680+
settings?.settings.deep_research_enabled && (
681+
<DeepResearchToggle
682+
deepResearchEnabled={deepResearchEnabled}
683+
toggleDeepResearch={toggleDeepResearch}
684+
/>
685+
)}
686+
687+
{forcedToolIds.length > 0 && (
688+
<div className="pl-1 flex items-center gap-2 text-blue-500">
689+
{forcedToolIds.map((toolId) => {
690+
const tool = selectedAssistant.tools.find(
691+
(tool) => tool.id === toolId
692+
);
693+
if (!tool) {
694+
return null;
695+
}
696+
return (
697+
<SelectedTool
698+
key={toolId}
699+
tool={tool}
700+
onClick={() => {
701+
setForcedToolIds((prev) =>
702+
prev.filter((id) => id !== toolId)
703+
);
704+
>>>>>>> e5547fb2c (enable all by default and persist user choice)
526705
}}
527706
/>
528707
))}

0 commit comments

Comments
 (0)