Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@ import { KnowledgeBase } from "@/types/knowledgeBase";
import ToolTestPanel from "./ToolTestPanel";
import { updateToolConfig } from "@/services/agentConfigService";
import KnowledgeBaseSelectorModal from "@/components/tool-config/KnowledgeBaseSelectorModal";
import {
useKnowledgeBasesForToolConfig,
} from "@/hooks/useKnowledgeBaseSelector";
import {
useKnowledgeBaseConfigChangeHandler,
} from "@/hooks/useKnowledgeBaseConfigChangeHandler";
import { useKnowledgeBasesForToolConfig } from "@/hooks/useKnowledgeBaseSelector";
import { useKnowledgeBaseConfigChangeHandler } from "@/hooks/useKnowledgeBaseConfigChangeHandler";
import { API_ENDPOINTS } from "@/services/api";
import log from "@/lib/logger";

Expand Down Expand Up @@ -95,6 +91,8 @@ export default function ToolConfigModal({
// DataMate URL from knowledge base configuration
const [knowledgeBaseDataMateUrl, setKnowledgeBaseDataMateUrl] =
useState<string>("");
// Track if knowledge base config has changed (server_url or api_key changed)
const [hasKbConfigChanged, setHasKbConfigChanged] = useState(false);
// Track if user has manually modified the datamate URL field
const [hasUserModifiedDatamateUrl, setHasUserModifiedDatamateUrl] =
useState(false);
Expand Down Expand Up @@ -206,12 +204,31 @@ export default function ToolConfigModal({
// Handle config change: clear knowledge base selection and refetch
// Uses shared hook for both Dify and DataMate tools
const handleKbConfigChange = useCallback(() => {
// Mark that config has changed - this prevents restoring from initialParams
setHasKbConfigChanged(true);

// Clear previous knowledge base selection
setSelectedKbIds([]);
setSelectedKbDisplayNames([]);

// Clear form value for knowledge base field (index_names or dataset_ids)
const kbFieldIndex = currentParams.findIndex(
(p) => p.name === "index_names" || p.name === "dataset_ids"
);
if (kbFieldIndex >= 0) {
form.setFieldValue(`param_${kbFieldIndex}`, []);
// Also clear the value in currentParams
const updatedParams = [...currentParams];
updatedParams[kbFieldIndex] = {
...updatedParams[kbFieldIndex],
value: [],
};
setCurrentParams(updatedParams);
}

// Refetch knowledge bases with new config
refetchKnowledgeBases();
}, [refetchKnowledgeBases]);
}, [refetchKnowledgeBases, currentParams, form]);

useKnowledgeBaseConfigChangeHandler({
toolKbType,
Expand Down Expand Up @@ -274,6 +291,7 @@ export default function ToolConfigModal({
if (!isOpen) {
setModalOpened(false);
setKnowledgeBaseDataMateUrl("");
setHasKbConfigChanged(false);
}
}, [isOpen]);

Expand Down Expand Up @@ -513,7 +531,9 @@ export default function ToolConfigModal({
if (selectedKbIds.length > 0 && knowledgeBases.length > 0) {
const displayNames = selectedKbIds.map((id) => {
// Use robust ID comparison
const kb = knowledgeBases.find((k) => String(k.id).trim() === String(id).trim());
const kb = knowledgeBases.find(
(k) => String(k.id).trim() === String(id).trim()
);
return kb?.display_name || kb?.name || id;
});
setSelectedKbDisplayNames(displayNames);
Expand All @@ -531,7 +551,9 @@ export default function ToolConfigModal({
setSelectedKbIds(validKbIds);
// Also update display names
const displayNames = validKbIds.map((id) => {
const kb = knowledgeBases.find((k) => String(k.id).trim() === String(id).trim());
const kb = knowledgeBases.find(
(k) => String(k.id).trim() === String(id).trim()
);
return kb?.display_name || kb?.name || id;
});
setSelectedKbDisplayNames(displayNames);
Expand All @@ -542,7 +564,16 @@ export default function ToolConfigModal({
// Force sync selectedKbIds when modal is about to open (kbSelectorVisible changes to true)
// This ensures the modal receives the correct selected IDs
useEffect(() => {
if (kbSelectorVisible && selectedKbIds.length === 0 && initialParams.length > 0) {
// Skip if config has changed - don't restore from initialParams after server_url/api_key change
if (hasKbConfigChanged) {
return;
}

if (
kbSelectorVisible &&
selectedKbIds.length === 0 &&
initialParams.length > 0
) {
// Parse initial index_names/dataset_ids value for knowledge base selection
if (toolRequiresKbSelection) {
const kbParam = initialParams.find(
Expand All @@ -568,13 +599,45 @@ export default function ToolConfigModal({
}
}
}
}, [kbSelectorVisible, initialParams, toolRequiresKbSelection]);
}, [
kbSelectorVisible,
initialParams,
toolRequiresKbSelection,
hasKbConfigChanged,
]);

// Trigger refetch when opening for knowledge base tools (with loading state support)
// Skip if initial load was already done to avoid duplicate API calls
// Reset when currentAgentId changes (i.e., when switching agents)
const hasTriggeredInitialRefetch = useRef(false);
const prevAgentIdRef = useRef<number | undefined>(undefined);

// Reset refetch flag when switching agents and invalidate cache to force fresh fetch
useEffect(() => {
if (currentAgentId !== prevAgentIdRef.current) {
prevAgentIdRef.current = currentAgentId;
hasTriggeredInitialRefetch.current = false;

// Invalidate knowledge base cache when switching agents to force fresh fetch
// This ensures we get the correct knowledge bases for the new agent's config
if (toolKbType === "dify_search") {
queryClient.invalidateQueries({
queryKey: ["knowledgeBases", "list", "dify_search"],
});
} else if (toolKbType === "datamate_search") {
queryClient.invalidateQueries({
queryKey: ["knowledgeBases", "list", "datamate_search"],
});
}
}
}, [currentAgentId, toolKbType, queryClient]);

useEffect(() => {
if (toolRequiresKbSelection && isOpen && !hasTriggeredInitialRefetch.current) {
if (
toolRequiresKbSelection &&
isOpen &&
!hasTriggeredInitialRefetch.current
) {
hasTriggeredInitialRefetch.current = true;
// For Dify, only refetch if we have valid config
if (toolKbType === "dify_search") {
Expand Down Expand Up @@ -1154,7 +1217,10 @@ export default function ToolConfigModal({
);
}
// Check if protocol is http or https
if (url.protocol !== "http:" && url.protocol !== "https:") {
if (
url.protocol !== "http:" &&
url.protocol !== "https:"
) {
return Promise.reject(
t("knowledgeBase.error.invalidUrlProtocol")
);
Expand Down
Loading