From 91cf02ed0fe525696c441c1271c0b1ef56b2f0c3 Mon Sep 17 00:00:00 2001 From: Rico Furtado Date: Mon, 22 Jun 2026 18:58:07 -0400 Subject: [PATCH 1/3] fix: update bucket ingestion messages for clarity and pre-select saved buckets Port of 68cb5be9 from the CPD branch to main. Fixes two issues with S3 and IBM COS connectors: clarifies that the settings dialog's bucket selection sets a default filter (not an immediate ingest), and pre-populates the Add Knowledge upload page with the buckets already saved in the connector config so users don't have to re-select them. Co-Authored-By: Claude Sonnet 4.6 --- .../_components/s3-settings-dialog.tsx | 4 ++-- .../settings/_components/s3-settings-form.tsx | 4 ++-- .../connectors/aws-s3/bucket-view.tsx | 3 +++ .../connectors/shared-bucket-view.tsx | 21 ++++++++++++++++++- .../ibm-cos/components/bucket-view.tsx | 3 +++ .../connectors/ibm-cos/settings-dialog.tsx | 4 ++-- .../connectors/ibm-cos/settings-form.tsx | 4 ++-- 7 files changed, 34 insertions(+), 9 deletions(-) diff --git a/frontend/app/settings/_components/s3-settings-dialog.tsx b/frontend/app/settings/_components/s3-settings-dialog.tsx index 942dcbdd0..5172be890 100644 --- a/frontend/app/settings/_components/s3-settings-dialog.tsx +++ b/frontend/app/settings/_components/s3-settings-dialog.tsx @@ -130,8 +130,8 @@ export default function S3SettingsDialog({ toast.success("Amazon S3 configured", { description: selectedBuckets.length > 0 - ? `Will ingest from: ${selectedBuckets.join(", ")}` - : "Will auto-discover and ingest all accessible buckets.", + ? `Filtered to: ${selectedBuckets.join(", ")}` + : "All accessible buckets are included.", icon: , }); diff --git a/frontend/app/settings/_components/s3-settings-form.tsx b/frontend/app/settings/_components/s3-settings-form.tsx index 523e8cf64..f8696a3f6 100644 --- a/frontend/app/settings/_components/s3-settings-form.tsx +++ b/frontend/app/settings/_components/s3-settings-form.tsx @@ -170,9 +170,9 @@ export function S3SettingsForm({
{buckets.length > 1 && ( diff --git a/frontend/components/connectors/aws-s3/bucket-view.tsx b/frontend/components/connectors/aws-s3/bucket-view.tsx index f2887084c..9c13236c4 100644 --- a/frontend/components/connectors/aws-s3/bucket-view.tsx +++ b/frontend/components/connectors/aws-s3/bucket-view.tsx @@ -2,6 +2,7 @@ import type { useSyncConnector } from "@/app/api/mutations/useSyncConnector"; import { useS3BucketStatusQuery } from "@/app/api/queries/useS3BucketStatusQuery"; +import { useS3DefaultsQuery } from "@/app/api/queries/useS3DefaultsQuery"; import { SharedBucketView } from "../shared-bucket-view"; export interface S3BucketViewProps { @@ -25,6 +26,7 @@ export function S3BucketView({ error: bucketsError, refetch, } = useS3BucketStatusQuery(connector.connectionId, { enabled: true }); + const { data: defaults } = useS3DefaultsQuery({ enabled: true }); return ( ); } diff --git a/frontend/components/connectors/shared-bucket-view.tsx b/frontend/components/connectors/shared-bucket-view.tsx index e6b91b94e..447479d40 100644 --- a/frontend/components/connectors/shared-bucket-view.tsx +++ b/frontend/components/connectors/shared-bucket-view.tsx @@ -2,7 +2,7 @@ import { useQueryClient } from "@tanstack/react-query"; import { ArrowLeft, FileSearch, FolderOpen, RefreshCw } from "lucide-react"; -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { toast } from "sonner"; import type { useSyncConnector } from "@/app/api/mutations/useSyncConnector"; import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery"; @@ -28,6 +28,7 @@ export interface SharedBucketViewProps { ) => void; onBack: () => void; onDone: () => void; + initialSelectedBuckets?: string[]; } export function SharedBucketView({ @@ -41,6 +42,7 @@ export function SharedBucketView({ addTask, onBack, onDone, + initialSelectedBuckets, }: SharedBucketViewProps) { const queryClient = useQueryClient(); const { isAuthenticated, isNoAuthMode } = useAuth(); @@ -53,12 +55,29 @@ export function SharedBucketView({ const [selectedBuckets, setSelectedBuckets] = useState>( new Set(), ); + const hasAppliedInitial = useRef(false); const [ingestSettings, setIngestSettings] = useSessionIngestSettings(); const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [browseDialogBucket, setBrowseDialogBucket] = useState( null, ); + useEffect(() => { + if ( + !hasAppliedInitial.current && + buckets?.length && + initialSelectedBuckets?.length + ) { + const valid = initialSelectedBuckets.filter((name) => + buckets.some((b) => b.name === name), + ); + if (valid.length) { + setSelectedBuckets(new Set(valid)); + hasAppliedInitial.current = true; + } + } + }, [buckets, initialSelectedBuckets]); + const invalidate = () => { queryClient.invalidateQueries({ queryKey: invalidateQueryKey }); }; diff --git a/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx b/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx index 326c38b3e..e8630bea8 100644 --- a/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx +++ b/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx @@ -3,6 +3,7 @@ import type { useSyncConnector } from "@/app/api/mutations/useSyncConnector"; import { SharedBucketView } from "@/components/connectors/shared-bucket-view"; import { useIBMCOSBucketStatusQuery } from "../useIBMCOSBucketStatusQuery"; +import { useIBMCOSDefaultsQuery } from "../useIBMCOSDefaultsQuery"; export interface IBMCOSBucketViewProps { connector: any; @@ -25,6 +26,7 @@ export function IBMCOSBucketView({ error: bucketsError, refetch, } = useIBMCOSBucketStatusQuery(connector.connectionId, { enabled: true }); + const { data: defaults } = useIBMCOSDefaultsQuery({ enabled: true }); return ( ); } diff --git a/frontend/enhancements/connectors/ibm-cos/settings-dialog.tsx b/frontend/enhancements/connectors/ibm-cos/settings-dialog.tsx index 2dd31dcf9..dadd41c3d 100644 --- a/frontend/enhancements/connectors/ibm-cos/settings-dialog.tsx +++ b/frontend/enhancements/connectors/ibm-cos/settings-dialog.tsx @@ -136,8 +136,8 @@ export default function IBMCOSSettingsDialog({ toast.success("IBM Cloud Object Storage configured", { description: selectedBuckets.length > 0 - ? `Will ingest from: ${selectedBuckets.join(", ")}` - : "Will auto-discover and ingest all accessible buckets.", + ? `Filtered to: ${selectedBuckets.join(", ")}` + : "All accessible buckets are included.", icon: , }); diff --git a/frontend/enhancements/connectors/ibm-cos/settings-form.tsx b/frontend/enhancements/connectors/ibm-cos/settings-form.tsx index 179e4de76..71b60e7ff 100644 --- a/frontend/enhancements/connectors/ibm-cos/settings-form.tsx +++ b/frontend/enhancements/connectors/ibm-cos/settings-form.tsx @@ -275,9 +275,9 @@ export function IBMCOSSettingsForm({
{buckets.length > 1 && ( From a19fb19a56401d4a616c88e849e4a0bc583b1d3f Mon Sep 17 00:00:00 2001 From: Rico Furtado Date: Mon, 22 Jun 2026 19:13:14 -0400 Subject: [PATCH 2/3] fix: guard bucket pre-selection against connection ID mismatch The defaults query returns the first S3/COS connection regardless of active status. Only pre-select saved bucket_names when the defaults connection_id matches the current connector.connectionId to avoid seeding the wrong buckets if a stale connection exists alongside the active one. Co-Authored-By: Claude Sonnet 4.6 --- frontend/components/connectors/aws-s3/bucket-view.tsx | 6 +++++- .../connectors/ibm-cos/components/bucket-view.tsx | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/components/connectors/aws-s3/bucket-view.tsx b/frontend/components/connectors/aws-s3/bucket-view.tsx index 9c13236c4..5e859828f 100644 --- a/frontend/components/connectors/aws-s3/bucket-view.tsx +++ b/frontend/components/connectors/aws-s3/bucket-view.tsx @@ -39,7 +39,11 @@ export function S3BucketView({ addTask={addTask} onBack={onBack} onDone={onDone} - initialSelectedBuckets={defaults?.bucket_names} + initialSelectedBuckets={ + defaults?.connection_id === connector.connectionId + ? defaults?.bucket_names + : undefined + } /> ); } diff --git a/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx b/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx index e8630bea8..41f8eff2f 100644 --- a/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx +++ b/frontend/enhancements/connectors/ibm-cos/components/bucket-view.tsx @@ -39,7 +39,11 @@ export function IBMCOSBucketView({ addTask={addTask} onBack={onBack} onDone={onDone} - initialSelectedBuckets={defaults?.bucket_names} + initialSelectedBuckets={ + defaults?.connection_id === connector.connectionId + ? defaults?.bucket_names + : undefined + } /> ); } From 40ae8b6ba54597ba266deba09817945b23231943 Mon Sep 17 00:00:00 2001 From: Rico Furtado Date: Mon, 22 Jun 2026 19:31:29 -0400 Subject: [PATCH 3/3] fix: prevent defaults from overwriting user bucket selections Two issues in the initial-selection effect: 1. hasAppliedInitial was only set when valid buckets were found, leaving the effect live across bucket refreshes and allowing stale defaults to overwrite selections made after a refetch. 2. No guard against the async race where buckets loads before initialSelectedBuckets: user clicks buckets, defaults arrive later and silently overwrite them. Fix: mark hasAppliedInitial unconditionally on first evaluation, and only apply defaults when selectedBuckets is still empty (user hasn't acted yet). Co-Authored-By: Claude Sonnet 4.6 --- .../components/connectors/shared-bucket-view.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/components/connectors/shared-bucket-view.tsx b/frontend/components/connectors/shared-bucket-view.tsx index 447479d40..013ede074 100644 --- a/frontend/components/connectors/shared-bucket-view.tsx +++ b/frontend/components/connectors/shared-bucket-view.tsx @@ -68,15 +68,17 @@ export function SharedBucketView({ buckets?.length && initialSelectedBuckets?.length ) { - const valid = initialSelectedBuckets.filter((name) => - buckets.some((b) => b.name === name), - ); - if (valid.length) { - setSelectedBuckets(new Set(valid)); - hasAppliedInitial.current = true; + hasAppliedInitial.current = true; + if (selectedBuckets.size === 0) { + const valid = initialSelectedBuckets.filter((name) => + buckets.some((b) => b.name === name), + ); + if (valid.length) { + setSelectedBuckets(new Set(valid)); + } } } - }, [buckets, initialSelectedBuckets]); + }, [buckets, initialSelectedBuckets]); // eslint-disable-line react-hooks/exhaustive-deps const invalidate = () => { queryClient.invalidateQueries({ queryKey: invalidateQueryKey });