mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-10 22:32:16 +02:00
feat: implement ensure_publication for zero_publication management
- Added the ensure_publication function to create and verify the zero_publication if it is missing, ensuring idempotency during database initialization. - Integrated ensure_publication into the create_db_and_tables function to prevent zero-cache crash loops on startup. - Introduced a self-check script to validate the ensure_publication functionality on a create_all-bootstrapped database. - Updated various components to reflect the transition from search space to workspace, including adjustments in imports and routing paths.
This commit is contained in:
parent
7562bc78ee
commit
a64c8205fe
164 changed files with 626 additions and 506 deletions
|
|
@ -29,7 +29,7 @@ import {
|
|||
globalModelConnectionsAtom,
|
||||
modelConnectionsAtom,
|
||||
} from "@/atoms/model-connections/model-connections-query.atoms";
|
||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||
import { activeWorkspaceIdAtom } from "@/atoms/workspaces/workspace-query.atoms";
|
||||
import {
|
||||
CitationMetadataProvider,
|
||||
useAllCitationMetadata,
|
||||
|
|
@ -491,7 +491,7 @@ export const AssistantMessage: FC = () => {
|
|||
const commentPanelRef = useRef<HTMLDivElement>(null);
|
||||
const commentTriggerRef = useRef<HTMLButtonElement>(null);
|
||||
const messageId = useAuiState(({ message }) => message?.id);
|
||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
|
||||
const dbMessageId = parseMessageId(messageId);
|
||||
const commentsEnabled = useAtomValue(commentsEnabledAtom);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useAtomValue } from "jotai";
|
|||
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { statusInboxItemsAtom } from "@/atoms/inbox/status-inbox.atom";
|
||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||
import { activeWorkspaceIdAtom } from "@/atoms/workspaces/workspace-query.atoms";
|
||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import { Tabs, TabsContent } from "@/components/ui/tabs";
|
||||
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
||||
|
|
@ -36,7 +36,7 @@ interface ConnectorIndicatorProps {
|
|||
|
||||
export const ConnectorIndicator = forwardRef<ConnectorIndicatorHandle, ConnectorIndicatorProps>(
|
||||
(_props, ref) => {
|
||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
|
||||
|
||||
// Real-time document type counts via Zero (updates instantly as docs are indexed)
|
||||
const documentTypeCounts = useZeroDocumentTypeCounts(searchSpaceId);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export interface CirclebackConfigProps extends ConnectorConfigProps {
|
|||
// Type-safe schema for webhook info response
|
||||
const circlebackWebhookInfoSchema = z.object({
|
||||
webhook_url: z.string(),
|
||||
search_space_id: z.number(),
|
||||
workspace_id: z.number(),
|
||||
method: z.string(),
|
||||
content_type: z.string(),
|
||||
description: z.string(),
|
||||
|
|
@ -40,12 +40,12 @@ export const CirclebackConfig: FC<CirclebackConfigProps> = ({ connector, onNameC
|
|||
const controller = new AbortController();
|
||||
|
||||
const doFetch = async () => {
|
||||
if (!connector.search_space_id) return;
|
||||
if (!connector.workspace_id) return;
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await authenticatedFetch(
|
||||
buildBackendUrl(`/api/v1/webhooks/circleback/${connector.search_space_id}/info`),
|
||||
buildBackendUrl(`/api/v1/webhooks/circleback/${connector.workspace_id}/info`),
|
||||
{ signal: controller.signal }
|
||||
);
|
||||
if (controller.signal.aborted) return;
|
||||
|
|
@ -70,7 +70,7 @@ export const CirclebackConfig: FC<CirclebackConfigProps> = ({ connector, onNameC
|
|||
|
||||
doFetch().catch(() => {});
|
||||
return () => controller.abort();
|
||||
}, [connector.search_space_id]);
|
||||
}, [connector.workspace_id]);
|
||||
|
||||
const handleNameChange = (value: string) => {
|
||||
setName(value);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useAtomValue } from "jotai";
|
|||
import { ArrowLeft, Info, RefreshCw } from "lucide-react";
|
||||
import { type FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||
import { activeWorkspaceIdAtom } from "@/atoms/workspaces/workspace-query.atoms";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
|
|
@ -78,7 +78,7 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
|||
onConfigChange,
|
||||
onNameChange,
|
||||
}) => {
|
||||
const searchSpaceIdAtom = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const searchSpaceIdAtom = useAtomValue(activeWorkspaceIdAtom);
|
||||
const isAuthExpired = connector.config?.auth_expired === true;
|
||||
const reauthEndpoint = getReauthEndpoint(connector);
|
||||
const [reauthing, setReauthing] = useState(false);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
updateConnectorMutationAtom,
|
||||
} from "@/atoms/connectors/connector-mutation.atoms";
|
||||
import { connectorsAtom } from "@/atoms/connectors/connector-query.atoms";
|
||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||
import { activeWorkspaceIdAtom } from "@/atoms/workspaces/workspace-query.atoms";
|
||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||
import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
||||
import { searchSourceConnector } from "@/contracts/types/connector.types";
|
||||
|
|
@ -58,7 +58,7 @@ function clearOAuthResultCookie(): void {
|
|||
}
|
||||
|
||||
export const useConnectorDialog = () => {
|
||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
|
||||
const { data: allConnectors, refetch: refetchAllConnectors } = useAtomValue(connectorsAtom);
|
||||
const { mutateAsync: indexConnector } = useAtomValue(indexConnectorMutationAtom);
|
||||
const { mutateAsync: updateConnector } = useAtomValue(updateConnectorMutationAtom);
|
||||
|
|
@ -165,7 +165,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: connector.id,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
start_date: format(startDate, "yyyy-MM-dd"),
|
||||
end_date: format(endDate, "yyyy-MM-dd"),
|
||||
},
|
||||
|
|
@ -418,7 +418,7 @@ export const useConnectorDialog = () => {
|
|||
enable_vision_llm: false,
|
||||
},
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -519,7 +519,7 @@ export const useConnectorDialog = () => {
|
|||
enable_vision_llm: false,
|
||||
},
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
},
|
||||
});
|
||||
// Refetch connectors to get the new one
|
||||
|
|
@ -612,7 +612,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: connector.id,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
start_date: startDateStr,
|
||||
end_date: endDateStr,
|
||||
},
|
||||
|
|
@ -847,7 +847,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: indexingConfig.connectorId,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
},
|
||||
body: {
|
||||
folders: selectedFolders || [],
|
||||
|
|
@ -870,14 +870,14 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: indexingConfig.connectorId,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await indexConnector({
|
||||
connector_id: indexingConfig.connectorId,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
start_date: startDateStr,
|
||||
end_date: endDateStr,
|
||||
},
|
||||
|
|
@ -1114,7 +1114,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: editingConnector.id,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
},
|
||||
body: {
|
||||
folders: selectedFolders || [],
|
||||
|
|
@ -1134,7 +1134,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: editingConnector.id,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
},
|
||||
});
|
||||
indexingDescription = "Re-indexing started with updated configuration.";
|
||||
|
|
@ -1143,7 +1143,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: editingConnector.id,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
start_date: startDateStr,
|
||||
end_date: endDateStr,
|
||||
},
|
||||
|
|
@ -1296,7 +1296,7 @@ export const useConnectorDialog = () => {
|
|||
await indexConnector({
|
||||
connector_id: connectorId,
|
||||
queryParams: {
|
||||
search_space_id: searchSpaceId,
|
||||
workspace_id: searchSpaceId,
|
||||
start_date: startDateStr,
|
||||
end_date: endDateStr,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useAtomValue } from "jotai";
|
|||
import { ArrowLeft, Plus, RefreshCw, Server } from "lucide-react";
|
||||
import { type FC, useCallback, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||
import { activeWorkspaceIdAtom } from "@/atoms/workspaces/workspace-query.atoms";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { EnumConnectorName } from "@/contracts/enums/connector";
|
||||
|
|
@ -44,7 +44,7 @@ export const ConnectorAccountsListView: FC<ConnectorAccountsListViewProps> = ({
|
|||
isConnecting = false,
|
||||
addButtonText,
|
||||
}) => {
|
||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
|
||||
const [reauthingId, setReauthingId] = useState<number | null>(null);
|
||||
const [confirmDisconnectId, setConfirmDisconnectId] = useState<number | null>(null);
|
||||
const [disconnectingId, setDisconnectingId] = useState<number | null>(null);
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export const YouTubeCrawlerView: FC<YouTubeCrawlerViewProps> = ({ searchSpaceId,
|
|||
{
|
||||
document_type: "YOUTUBE_VIDEO",
|
||||
content: videoUrls,
|
||||
search_space_id: parseInt(searchSpaceId, 10),
|
||||
workspace_id: parseInt(searchSpaceId, 10),
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||
import { activeWorkspaceIdAtom } from "@/atoms/workspaces/workspace-query.atoms";
|
||||
import { DocumentUploadTab } from "@/components/sources/DocumentUploadTab";
|
||||
import {
|
||||
Dialog,
|
||||
|
|
@ -90,7 +90,7 @@ const DocumentUploadPopupContent: FC<{
|
|||
isOpen: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
}> = ({ isOpen, onOpenChange }) => {
|
||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||
const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
|
||||
|
||||
if (!searchSpaceId) return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ function FilePathLink({ path, className }: { path: string; className?: string })
|
|||
const openEditorPanel = useSetAtom(openEditorPanelAtom);
|
||||
const params = useParams();
|
||||
const electronAPI = useElectronAPI();
|
||||
const searchSpaceIdParam = params?.search_space_id;
|
||||
const searchSpaceIdParam = params?.workspace_id;
|
||||
const parsedSearchSpaceId = Array.isArray(searchSpaceIdParam)
|
||||
? Number(searchSpaceIdParam[0])
|
||||
: Number(searchSpaceIdParam);
|
||||
|
|
@ -228,7 +228,7 @@ function FilePathLink({ path, className }: { path: string; className?: string })
|
|||
if (!resolvedSearchSpaceId || !path.startsWith("/documents/")) return;
|
||||
try {
|
||||
const doc = await documentsApiService.getDocumentByVirtualPath({
|
||||
search_space_id: resolvedSearchSpaceId,
|
||||
workspace_id: resolvedSearchSpaceId,
|
||||
virtual_path: path,
|
||||
});
|
||||
openEditorPanel({
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ const Composer: FC = () => {
|
|||
const prevMentionedDocsRef = useRef<Map<string, MentionedDocumentInfo>>(new Map());
|
||||
const documentPickerRef = useRef<DocumentMentionPickerRef>(null);
|
||||
const promptPickerRef = useRef<PromptPickerRef>(null);
|
||||
const { search_space_id, chat_id } = useParams();
|
||||
const { workspace_id, chat_id } = useParams();
|
||||
const aui = useAui();
|
||||
// Desktop-only auto-focus; on mobile, programmatic focus would
|
||||
// summon the soft keyboard on every picker close / thread switch.
|
||||
|
|
@ -824,7 +824,7 @@ const Composer: FC = () => {
|
|||
|
||||
const handleDocumentsMention = useCallback(
|
||||
(mentions: MentionedDocumentInfo[]) => {
|
||||
const parsedSearchSpaceId = Number(search_space_id);
|
||||
const parsedSearchSpaceId = Number(workspace_id);
|
||||
const editorMentionedDocs = editorRef.current?.getMentionedDocuments() ?? [];
|
||||
const editorDocKeys = new Set(editorMentionedDocs.map((doc) => getMentionDocKey(doc)));
|
||||
|
||||
|
|
@ -844,7 +844,7 @@ const Composer: FC = () => {
|
|||
setMentionQuery("");
|
||||
setSuggestionAnchorPoint(null);
|
||||
},
|
||||
[search_space_id]
|
||||
[workspace_id]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -893,7 +893,7 @@ const Composer: FC = () => {
|
|||
<ComposerSuggestionPopoverContent side="top">
|
||||
<DocumentMentionPicker
|
||||
ref={documentPickerRef}
|
||||
searchSpaceId={Number(search_space_id)}
|
||||
searchSpaceId={Number(workspace_id)}
|
||||
enableChatMentions
|
||||
currentChatId={threadId}
|
||||
onSelectionChange={handleDocumentsMention}
|
||||
|
|
@ -959,7 +959,7 @@ const Composer: FC = () => {
|
|||
</div>
|
||||
<ComposerAction
|
||||
isBlockedByOtherUser={isBlockedByOtherUser}
|
||||
searchSpaceId={Number(search_space_id)}
|
||||
searchSpaceId={Number(workspace_id)}
|
||||
onChatModelSelected={handleChatModelSelected}
|
||||
/>
|
||||
<ConnectorIndicator showTrigger={false} />
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const UserTextPart: FC = () => {
|
|||
const openEditorPanel = useSetAtom(openEditorPanelAtom);
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
const searchSpaceIdParam = params?.search_space_id;
|
||||
const searchSpaceIdParam = params?.workspace_id;
|
||||
const parsedSearchSpaceId = Array.isArray(searchSpaceIdParam)
|
||||
? Number(searchSpaceIdParam[0])
|
||||
: Number(searchSpaceIdParam);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue