diff --git a/surfsense_web/components/sources/DocumentUploadTab.tsx b/surfsense_web/components/sources/DocumentUploadTab.tsx
index 3d45ac2ae..278632ecd 100644
--- a/surfsense_web/components/sources/DocumentUploadTab.tsx
+++ b/surfsense_web/components/sources/DocumentUploadTab.tsx
@@ -41,7 +41,7 @@ import {
} from "@/lib/supported-extensions";
interface DocumentUploadTabProps {
- searchSpaceId: string;
+ workspaceId: string;
onSuccess?: () => void;
onAccordionStateChange?: (isExpanded: boolean) => void;
}
@@ -132,7 +132,7 @@ const toggleRowClass =
"flex items-center justify-between rounded-lg bg-slate-400/5 dark:bg-white/5 p-3";
export function DocumentUploadTab({
- searchSpaceId,
+ workspaceId,
onSuccess,
onAccordionStateChange,
}: DocumentUploadTabProps) {
@@ -319,7 +319,7 @@ export function DocumentUploadTab({
setUploadProgress(0);
setIsFolderUploading(true);
const total = folderUpload.entries.length;
- trackDocumentUploadStarted(Number(searchSpaceId), total, totalFileSize);
+ trackDocumentUploadStarted(Number(workspaceId), total, totalFileSize);
try {
const batches: FolderEntry[][] = [];
@@ -364,7 +364,7 @@ export function DocumentUploadTab({
batch.map((e) => e.file),
{
folder_name: folderUpload.folderName,
- workspace_id: Number(searchSpaceId),
+ workspace_id: Number(workspaceId),
relative_paths: batch.map((e) => e.relativePath),
root_folder_id: rootFolderId,
use_vision_llm: useVisionLlm,
@@ -380,13 +380,13 @@ export function DocumentUploadTab({
setUploadProgress(Math.round((uploaded / total) * 100));
}
- trackDocumentUploadSuccess(Number(searchSpaceId), total);
+ trackDocumentUploadSuccess(Number(workspaceId), total);
toast(t("upload_initiated"), { description: t("upload_initiated_desc") });
setFolderUpload(null);
onSuccess?.();
} catch (error) {
const message = error instanceof Error ? error.message : "Upload failed";
- trackDocumentUploadFailure(Number(searchSpaceId), message);
+ trackDocumentUploadFailure(Number(workspaceId), message);
toast(t("upload_error"), {
description: `${t("upload_error_desc")}: ${message}`,
});
@@ -403,7 +403,7 @@ export function DocumentUploadTab({
}
setUploadProgress(0);
- trackDocumentUploadStarted(Number(searchSpaceId), files.length, totalFileSize);
+ trackDocumentUploadStarted(Number(workspaceId), files.length, totalFileSize);
progressIntervalRef.current = setInterval(() => {
setUploadProgress((prev) => (prev >= 90 ? prev : prev + Math.random() * 10));
@@ -413,7 +413,7 @@ export function DocumentUploadTab({
uploadDocuments(
{
files: rawFiles,
- workspace_id: Number(searchSpaceId),
+ workspace_id: Number(workspaceId),
use_vision_llm: useVisionLlm,
processing_mode: processingMode,
},
@@ -421,7 +421,7 @@ export function DocumentUploadTab({
onSuccess: () => {
if (progressIntervalRef.current) clearInterval(progressIntervalRef.current);
setUploadProgress(100);
- trackDocumentUploadSuccess(Number(searchSpaceId), files.length);
+ trackDocumentUploadSuccess(Number(workspaceId), files.length);
toast(t("upload_initiated"), { description: t("upload_initiated_desc") });
onSuccess?.();
},
@@ -429,7 +429,7 @@ export function DocumentUploadTab({
if (progressIntervalRef.current) clearInterval(progressIntervalRef.current);
setUploadProgress(0);
const message = error instanceof Error ? error.message : "Upload failed";
- trackDocumentUploadFailure(Number(searchSpaceId), message);
+ trackDocumentUploadFailure(Number(workspaceId), message);
toast(t("upload_error"), {
description: `${t("upload_error_desc")}: ${message}`,
});
diff --git a/surfsense_web/components/sources/FolderWatchDialog.tsx b/surfsense_web/components/sources/FolderWatchDialog.tsx
index 7a64f3835..74d7c3a59 100644
--- a/surfsense_web/components/sources/FolderWatchDialog.tsx
+++ b/surfsense_web/components/sources/FolderWatchDialog.tsx
@@ -24,7 +24,7 @@ export interface SelectedFolder {
interface FolderWatchDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
- searchSpaceId: number;
+ workspaceId: number;
onSuccess?: () => void;
initialFolder?: SelectedFolder | null;
}
@@ -41,7 +41,7 @@ export const DEFAULT_EXCLUDE_PATTERNS = [
export function FolderWatchDialog({
open,
onOpenChange,
- searchSpaceId,
+ workspaceId,
onSuccess,
initialFolder,
}: FolderWatchDialogProps) {
@@ -91,7 +91,7 @@ export function FolderWatchDialog({
const rootFolderId = await uploadFolderScan({
folderPath: selectedFolder.path,
folderName: selectedFolder.name,
- searchSpaceId,
+ workspaceId,
excludePatterns: DEFAULT_EXCLUDE_PATTERNS,
fileExtensions: supportedExtensions,
onProgress: setProgress,
@@ -104,7 +104,7 @@ export function FolderWatchDialog({
excludePatterns: DEFAULT_EXCLUDE_PATTERNS,
fileExtensions: supportedExtensions,
rootFolderId: rootFolderId ?? null,
- searchSpaceId,
+ workspaceId,
active: true,
});
@@ -124,7 +124,7 @@ export function FolderWatchDialog({
setSubmitting(false);
setProgress(null);
}
- }, [selectedFolder, searchSpaceId, supportedExtensions, onOpenChange, onSuccess]);
+ }, [selectedFolder, workspaceId, supportedExtensions, onOpenChange, onSuccess]);
const handleOpenChange = useCallback(
(nextOpen: boolean) => {
diff --git a/surfsense_web/components/tool-ui/automation/create-automation.tsx b/surfsense_web/components/tool-ui/automation/create-automation.tsx
index ffc8aa5b8..768372fb0 100644
--- a/surfsense_web/components/tool-ui/automation/create-automation.tsx
+++ b/surfsense_web/components/tool-ui/automation/create-automation.tsx
@@ -108,9 +108,9 @@ function ApprovalCard({ args, interruptData, onDecision }: ApprovalCardProps) {
const draft = useMemo(() => extractDraft(effectiveArgs), [effectiveArgs]);
// Per-automation model selection. The card always supplies models (chosen
- // here, not snapshotted from the search space), so Approve dispatches an
+ // here, not snapshotted from the workspace), so Approve dispatches an
// `edit` decision carrying `definition.models`.
- const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
+ const workspaceId = useAtomValue(activeWorkspaceIdAtom);
const eligibleModels = useAutomationEligibleModels();
const [modelSelection, setModelSelection] = useState
({
chatModelId: 0,
@@ -156,7 +156,7 @@ function ApprovalCard({ args, interruptData, onDecision }: ApprovalCardProps) {
const plan = Array.isArray(baseDefinition.plan) ? baseDefinition.plan : [];
const triggers = Array.isArray(baseArgs.triggers) ? baseArgs.triggers : [];
trackAutomationChatApproved({
- workspace_id: searchSpaceId ? Number(searchSpaceId) : undefined,
+ workspace_id: workspaceId ? Number(workspaceId) : undefined,
edited: pendingEdits !== null,
task_count: plan.length,
trigger_type:
@@ -184,17 +184,17 @@ function ApprovalCard({ args, interruptData, onDecision }: ApprovalCardProps) {
args,
pendingEdits,
resolvedModels,
- searchSpaceId,
+ workspaceId,
]);
const handleReject = useCallback(() => {
if (phase !== "pending" || !canReject || isEditing) return;
setRejected();
trackAutomationChatRejected({
- workspace_id: searchSpaceId ? Number(searchSpaceId) : undefined,
+ workspace_id: workspaceId ? Number(workspaceId) : undefined,
});
onDecision({ type: "reject", message: "User rejected the automation draft." });
- }, [phase, canReject, isEditing, setRejected, onDecision, searchSpaceId]);
+ }, [phase, canReject, isEditing, setRejected, onDecision, workspaceId]);
useEffect(() => {
if (isEditing) return;
@@ -268,7 +268,7 @@ function ApprovalCard({ args, interruptData, onDecision }: ApprovalCardProps) {
setPendingEdits(parsed);
setIsEditing(false);
trackAutomationChatDraftEdited({
- workspace_id: searchSpaceId ? Number(searchSpaceId) : undefined,
+ workspace_id: workspaceId ? Number(workspaceId) : undefined,
});
}}
onCancel={() => setIsEditing(false)}
@@ -284,7 +284,7 @@ function ApprovalCard({ args, interruptData, onDecision }: ApprovalCardProps) {
Models
setModelSelection((prev) => ({ ...prev, ...patch }))}
/>
@@ -385,7 +385,7 @@ function JsonEditor({ initialValue, onSave, onCancel }: JsonEditorProps) {
// ----------------------------------------------------------------------------
function SavedCard({ result }: { result: SavedResult }) {
- const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
+ const workspaceId = useAtomValue(activeWorkspaceIdAtom);
const tracked = useRef(false);
useEffect(() => {
if (tracked.current) return;
@@ -393,12 +393,12 @@ function SavedCard({ result }: { result: SavedResult }) {
trackAutomationChatCreateSucceeded({
automation_id: result.automation_id,
name: result.name,
- workspace_id: searchSpaceId ? Number(searchSpaceId) : undefined,
+ workspace_id: workspaceId ? Number(workspaceId) : undefined,
});
- }, [result.automation_id, result.name, searchSpaceId]);
+ }, [result.automation_id, result.name, workspaceId]);
- const detailHref = searchSpaceId
- ? `/dashboard/${searchSpaceId}/automations/${result.automation_id}`
+ const detailHref = workspaceId
+ ? `/dashboard/${workspaceId}/automations/${result.automation_id}`
: null;
return (
@@ -429,7 +429,7 @@ function SavedCard({ result }: { result: SavedResult }) {
}
function InvalidCard({ result }: { result: InvalidResult }) {
- const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
+ const workspaceId = useAtomValue(activeWorkspaceIdAtom);
const tracked = useRef(false);
useEffect(() => {
if (tracked.current) return;
@@ -437,9 +437,9 @@ function InvalidCard({ result }: { result: InvalidResult }) {
trackAutomationChatCreateFailed({
reason: "invalid",
issue_count: result.issues.length,
- workspace_id: searchSpaceId ? Number(searchSpaceId) : undefined,
+ workspace_id: workspaceId ? Number(workspaceId) : undefined,
});
- }, [result.issues.length, searchSpaceId]);
+ }, [result.issues.length, workspaceId]);
return (
@@ -464,7 +464,7 @@ function InvalidCard({ result }: { result: InvalidResult }) {
}
function ErrorCard({ result }: { result: ErrorResult }) {
- const searchSpaceId = useAtomValue(activeWorkspaceIdAtom);
+ const workspaceId = useAtomValue(activeWorkspaceIdAtom);
const tracked = useRef(false);
useEffect(() => {
if (tracked.current) return;
@@ -472,9 +472,9 @@ function ErrorCard({ result }: { result: ErrorResult }) {
trackAutomationChatCreateFailed({
reason: "error",
message: result.message,
- workspace_id: searchSpaceId ? Number(searchSpaceId) : undefined,
+ workspace_id: workspaceId ? Number(workspaceId) : undefined,
});
- }, [result.message, searchSpaceId]);
+ }, [result.message, workspaceId]);
return (
diff --git a/surfsense_web/components/workspace-form.tsx b/surfsense_web/components/workspace-form.tsx
index e87b36504..4c23a724f 100644
--- a/surfsense_web/components/workspace-form.tsx
+++ b/surfsense_web/components/workspace-form.tsx
@@ -35,15 +35,15 @@ import { Tilt } from "@/components/ui/tilt";
import { cn } from "@/lib/utils";
// Define the form schema with Zod
-const searchSpaceFormSchema = z.object({
+const workspaceFormSchema = z.object({
name: z.string().min(1, "Name is required"),
description: z.string().optional(),
});
// Define the type for the form values
-type SearchSpaceFormValues = z.infer
;
+type WorkspaceFormValues = z.infer;
-interface SearchSpaceFormProps {
+interface WorkspaceFormProps {
onSubmit?: (data: { name: string; description?: string }) => void;
onDelete?: () => void;
className?: string;
@@ -51,19 +51,19 @@ interface SearchSpaceFormProps {
initialData?: { name: string; description?: string };
}
-export function SearchSpaceForm({
+export function WorkspaceForm({
onSubmit,
onDelete,
className,
isEditing = false,
initialData = { name: "", description: "" },
-}: SearchSpaceFormProps) {
+}: WorkspaceFormProps) {
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const router = useRouter();
// Initialize the form with React Hook Form and Zod validation
- const form = useForm({
- resolver: zodResolver(searchSpaceFormSchema),
+ const form = useForm({
+ resolver: zodResolver(workspaceFormSchema),
defaultValues: {
name: initialData.name,
description: initialData.description,
@@ -71,7 +71,7 @@ export function SearchSpaceForm({
});
// Handle form submission
- const handleFormSubmit = (values: SearchSpaceFormValues) => {
+ const handleFormSubmit = (values: WorkspaceFormValues) => {
if (onSubmit) {
onSubmit(values);
}
@@ -119,7 +119,7 @@ export function SearchSpaceForm({
- {isEditing ? "Edit Search Space" : "Create Search Space"}
+ {isEditing ? "Edit Workspace" : "Create Workspace"}
{isEditing && onDelete && (
@@ -193,7 +193,7 @@ export function SearchSpaceForm({
)}
- A search space is your personal workspace. Connect external sources, upload documents,
+ A workspace is your personal workspace. Connect external sources, upload documents,
take notes, and get work done with AI agents.
@@ -211,9 +211,9 @@ export function SearchSpaceForm({
Name
-
+
- A unique name for your search space.
+ A unique name for your workspace.
)}
@@ -228,10 +228,10 @@ export function SearchSpaceForm({
Description (optional)
-
+
- A brief description of what this search space will be used for.
+ A brief description of what this workspace will be used for.
@@ -250,4 +250,4 @@ export function SearchSpaceForm({
);
}
-export default SearchSpaceForm;
+export default WorkspaceForm;
diff --git a/surfsense_web/content/docs/connectors/baidu-search.mdx b/surfsense_web/content/docs/connectors/baidu-search.mdx
index b6e33f310..d773f4736 100644
--- a/surfsense_web/content/docs/connectors/baidu-search.mdx
+++ b/surfsense_web/content/docs/connectors/baidu-search.mdx
@@ -93,7 +93,7 @@ Baidu Search does not create indexed documents in your knowledge base. It runs w
**No Baidu results appear**
-- Confirm the Baidu Search connector is active in the current search space.
+- Confirm the Baidu Search connector is active in the current workspace.
- Try a Chinese query with clear search intent, for example `百度智能云千帆 AppBuilder 最新功能`.
- Check whether other web search engines are returning results. If none are, review the general [Web Search](/docs/how-to/web-search) setup.
diff --git a/surfsense_web/content/docs/connectors/circleback.mdx b/surfsense_web/content/docs/connectors/circleback.mdx
index 709e35f45..743117952 100644
--- a/surfsense_web/content/docs/connectors/circleback.mdx
+++ b/surfsense_web/content/docs/connectors/circleback.mdx
@@ -44,7 +44,7 @@ The Circleback connector uses a **webhook-based integration**. Unlike other conn
3. Click **Connect** to create the connector
-Circleback uses webhooks, so no API key or authentication is required. The webhook URL is unique to your search space.
+Circleback uses webhooks, so no API key or authentication is required. The webhook URL is unique to your workspace.
### Step 2: Copy Your Webhook URL
@@ -57,7 +57,7 @@ After creating the connector:
The webhook URL looks like:
```
-https://your-surfsense-url/api/v1/webhooks/circleback/{search_space_id}
+https://your-surfsense-url/api/v1/webhooks/circleback/{workspace_id}
```
### Step 3: Configure Circleback Automation
@@ -101,7 +101,7 @@ Once configured, new meetings will automatically appear in SurfSense after Circl
1. Attend or process a meeting with Circleback
2. Wait for Circleback to complete processing (usually a few minutes after the meeting ends)
-3. Check your SurfSense search space for the new meeting document
+3. Check your SurfSense workspace for the new meeting document
Each meeting document includes:
- A direct link to view the meeting on Circleback
diff --git a/surfsense_web/content/docs/connectors/obsidian.mdx b/surfsense_web/content/docs/connectors/obsidian.mdx
index 19c6a34c6..e69024913 100644
--- a/surfsense_web/content/docs/connectors/obsidian.mdx
+++ b/surfsense_web/content/docs/connectors/obsidian.mdx
@@ -29,7 +29,7 @@ This works for cloud and self-hosted deployments, including desktop and mobile c
3. In Obsidian, open **Settings → SurfSense**.
4. Paste your SurfSense API token from the user settings section.
5. Paste your Server URL in the plugin setting: either your SurfSense main domain (if `/api/v1` rewrites are enabled) or your direct backend URL.
-6. Choose the Search Space in the plugin, then the first sync should run automatically.
+6. Choose the Workspace in the plugin, then the first sync should run automatically.
7. Confirm the connector appears as **Obsidian - <vault>** in SurfSense.
## Install via BRAT (recommended)
@@ -55,7 +55,7 @@ If you previously used the legacy Obsidian connector architecture, migrate to th
## Troubleshooting
**Plugin connects but no files appear**
-- Verify the plugin is pointed to the correct Search Space.
+- Verify the plugin is pointed to the correct Workspace.
- Trigger a manual sync from the plugin settings.
- Confirm your API token is valid and not expired.
diff --git a/surfsense_web/content/docs/how-to/realtime-collaboration.mdx b/surfsense_web/content/docs/how-to/realtime-collaboration.mdx
index 73032c798..3031511fd 100644
--- a/surfsense_web/content/docs/how-to/realtime-collaboration.mdx
+++ b/surfsense_web/content/docs/how-to/realtime-collaboration.mdx
@@ -5,17 +5,17 @@ description: How to invite teammates, share chats, and collaborate in realtime o
# Realtime Collaboration
-SurfSense supports realtime collaboration so your team can work together on shared Search Spaces and chats. This guide walks you through the full setup.
+SurfSense supports realtime collaboration so your team can work together on shared Workspaces and chats. This guide walks you through the full setup.
## Step 1: Invite Members
-Go to the **Manage Members** page in your Search Space and create an invite for your teammates.
+Go to the **Manage Members** page in your Workspace and create an invite for your teammates.
## Step 2: Teammate Joins
-Your teammate accepts the invite and the Search Space becomes shared between you.
+Your teammate accepts the invite and the Workspace becomes shared between you.
diff --git a/surfsense_web/content/docs/local-models/lm-studio.mdx b/surfsense_web/content/docs/local-models/lm-studio.mdx
index 6877786e5..d43ac1532 100644
--- a/surfsense_web/content/docs/local-models/lm-studio.mdx
+++ b/surfsense_web/content/docs/local-models/lm-studio.mdx
@@ -6,7 +6,7 @@ description: Connect LM Studio to SurfSense
# Connect LM Studio
Connect to your LM Studio local server. Add it from
-**Search Space Settings > Models**.
+**Workspace Settings > Models**.
## Base URL
@@ -51,7 +51,7 @@ Replace `` with the LAN IP or domain for that machine.
## Add the Connection
-1. Open Search Space Settings.
+1. Open Workspace Settings.
2. Go to Models.
3. Select LM Studio.
4. Set API Base URL.
diff --git a/surfsense_web/content/docs/local-models/ollama.mdx b/surfsense_web/content/docs/local-models/ollama.mdx
index b062d98b0..fdf9f30e6 100644
--- a/surfsense_web/content/docs/local-models/ollama.mdx
+++ b/surfsense_web/content/docs/local-models/ollama.mdx
@@ -6,7 +6,7 @@ description: Connect Ollama to SurfSense
# Connect Ollama
Connect to your Ollama local server. Add it from
-**Search Space Settings > Models**.
+**Workspace Settings > Models**.
## Base URL
@@ -52,7 +52,7 @@ Replace `` with the LAN IP or domain for that machine.
## Add the Connection
-1. Open Search Space Settings.
+1. Open Workspace Settings.
2. Go to Models.
3. Select Ollama.
4. Set API Base URL.
diff --git a/surfsense_web/content/docs/local-models/other-local-servers.mdx b/surfsense_web/content/docs/local-models/other-local-servers.mdx
index 669684929..b747d5147 100644
--- a/surfsense_web/content/docs/local-models/other-local-servers.mdx
+++ b/surfsense_web/content/docs/local-models/other-local-servers.mdx
@@ -56,7 +56,7 @@ http://:/v1
## Add the Connection
-1. Open Search Space Settings.
+1. Open Workspace Settings.
2. Go to Models.
3. Select OpenAI Compatible.
4. Set API Base URL.
diff --git a/surfsense_web/content/docs/manual-installation.mdx b/surfsense_web/content/docs/manual-installation.mdx
index ab09b4155..f35939048 100644
--- a/surfsense_web/content/docs/manual-installation.mdx
+++ b/surfsense_web/content/docs/manual-installation.mdx
@@ -685,7 +685,7 @@ To verify your installation:
1. Open your browser and navigate to `http://localhost:3000`
2. Sign in with your Google account (or local credentials if `AUTH_TYPE=LOCAL`)
-3. Create a search space and try uploading a document
+3. Create a workspace and try uploading a document
4. Watch the upload status update live without refreshing. This confirms zero-cache is wired up correctly
5. Test the chat functionality with your uploaded content
@@ -709,7 +709,7 @@ To verify your installation:
Now that you have SurfSense running locally, you can explore its features:
-- Create search spaces for organizing your content
+- Create workspaces for organizing your content
- Upload documents or use the browser extension to save webpages
- Ask questions about your saved content
- Explore the advanced RAG capabilities
diff --git a/surfsense_web/content/docs/messaging-channels/discord.mdx b/surfsense_web/content/docs/messaging-channels/discord.mdx
index c0874dfe3..7671b0741 100644
--- a/surfsense_web/content/docs/messaging-channels/discord.mdx
+++ b/surfsense_web/content/docs/messaging-channels/discord.mdx
@@ -64,7 +64,7 @@ callback.
1. Discord sends a `MESSAGE_CREATE` event over its WebSocket API.
2. SurfSense stores the event in the durable gateway inbox.
-3. SurfSense resolves the Discord user binding to a SurfSense user and search space.
+3. SurfSense resolves the Discord user binding to a SurfSense user and workspace.
4. SurfSense runs the backend agent with that user's permissions.
5. The agent reply is posted back to the same Discord channel.
diff --git a/surfsense_web/content/docs/messaging-channels/slack.mdx b/surfsense_web/content/docs/messaging-channels/slack.mdx
index 4e001d13a..8c73e553b 100644
--- a/surfsense_web/content/docs/messaging-channels/slack.mdx
+++ b/surfsense_web/content/docs/messaging-channels/slack.mdx
@@ -79,6 +79,6 @@ the Slack app to your workspace so Slack grants the updated permissions.
1. Slack sends an `app_mention` event to SurfSense.
2. SurfSense verifies the Slack signature and stores the event in the gateway inbox.
-3. SurfSense resolves the Slack user binding to a SurfSense user and search space.
+3. SurfSense resolves the Slack user binding to a SurfSense user and workspace.
4. SurfSense runs the backend agent with that user's permissions.
5. The agent reply is posted back in the same Slack thread.
diff --git a/surfsense_web/content/docs/messaging-channels/telegram.mdx b/surfsense_web/content/docs/messaging-channels/telegram.mdx
index 3487da864..35fa1c4fb 100644
--- a/surfsense_web/content/docs/messaging-channels/telegram.mdx
+++ b/surfsense_web/content/docs/messaging-channels/telegram.mdx
@@ -59,4 +59,4 @@ webhook or pending `getUpdates` session before relying on the new mode.
2. The user starts Telegram pairing.
3. SurfSense provides a pairing code or bot link.
4. The user sends the pairing command to the Telegram bot.
-5. SurfSense binds that Telegram chat to the selected search space.
+5. SurfSense binds that Telegram chat to the selected workspace.
diff --git a/surfsense_web/content/docs/messaging-channels/troubleshooting.mdx b/surfsense_web/content/docs/messaging-channels/troubleshooting.mdx
index bdd385e28..e43015b4c 100644
--- a/surfsense_web/content/docs/messaging-channels/troubleshooting.mdx
+++ b/surfsense_web/content/docs/messaging-channels/troubleshooting.mdx
@@ -63,4 +63,4 @@ Check that:
- Message Content Intent is enabled.
- The bot can view and send messages in the channel.
- Exactly one backend process is running the Discord listener.
-- The Discord user is paired to a SurfSense user and search space.
+- The Discord user is paired to a SurfSense user and workspace.
diff --git a/surfsense_web/content/docs/testing.mdx b/surfsense_web/content/docs/testing.mdx
index 9a79cae4e..7c51f38f1 100644
--- a/surfsense_web/content/docs/testing.mdx
+++ b/surfsense_web/content/docs/testing.mdx
@@ -101,5 +101,5 @@ import pytest
pytestmark = pytest.mark.integration # or pytest.mark.unit
```
-3. Use fixtures from `conftest.py` — `client`, `headers`, `search_space_id`, and `cleanup_doc_ids` are available to integration tests. Unit tests get `make_connector_document` and sample ID fixtures.
+3. Use fixtures from `conftest.py` — `client`, `headers`, `workspace_id`, and `cleanup_doc_ids` are available to integration tests. Unit tests get `make_connector_document` and sample ID fixtures.
4. Register any new markers in `pyproject.toml` under `markers`.
diff --git a/surfsense_web/contracts/types/automation.types.ts b/surfsense_web/contracts/types/automation.types.ts
index c9a286542..f90d6a52d 100644
--- a/surfsense_web/contracts/types/automation.types.ts
+++ b/surfsense_web/contracts/types/automation.types.ts
@@ -61,7 +61,7 @@ export const inputs = z.object({
export type Inputs = z.infer;
// Captured model snapshot (server-managed). Set at create time and preserved
-// across edits so runs are insulated from later chat/search-space model changes.
+// across edits so runs are insulated from later chat/workspace model changes.
export const automationModels = z.object({
chat_model_id: z.number().int().default(0),
image_gen_model_id: z.number().int().default(0),
diff --git a/surfsense_web/contracts/types/chat-threads.types.ts b/surfsense_web/contracts/types/chat-threads.types.ts
index 1362d5fc1..e4b45ad61 100644
--- a/surfsense_web/contracts/types/chat-threads.types.ts
+++ b/surfsense_web/contracts/types/chat-threads.types.ts
@@ -59,7 +59,7 @@ export const publicChatSnapshotDetail = z.object({
});
/**
- * List public chat snapshots for search space
+ * List public chat snapshots for workspace
*/
export const publicChatSnapshotsBySpaceRequest = z.object({
workspace_id: z.number(),
diff --git a/surfsense_web/contracts/types/members.types.ts b/surfsense_web/contracts/types/members.types.ts
index 5d3516a66..4872739c5 100644
--- a/surfsense_web/contracts/types/members.types.ts
+++ b/surfsense_web/contracts/types/members.types.ts
@@ -54,11 +54,11 @@ export const deleteMembershipResponse = z.object({
/**
* Leave workspace
*/
-export const leaveSearchSpaceRequest = z.object({
+export const leaveWorkspaceRequest = z.object({
workspace_id: z.number(),
});
-export const leaveSearchSpaceResponse = z.object({
+export const leaveWorkspaceResponse = z.object({
message: z.string(),
});
@@ -84,7 +84,7 @@ export type UpdateMembershipRequest = z.infer;
export type UpdateMembershipResponse = z.infer;
export type DeleteMembershipRequest = z.infer;
export type DeleteMembershipResponse = z.infer;
-export type LeaveSearchSpaceRequest = z.infer;
-export type LeaveSearchSpaceResponse = z.infer;
+export type LeaveWorkspaceRequest = z.infer;
+export type LeaveWorkspaceResponse = z.infer;
export type GetMyAccessRequest = z.infer;
export type GetMyAccessResponse = z.infer;
diff --git a/surfsense_web/contracts/types/workspace.types.ts b/surfsense_web/contracts/types/workspace.types.ts
index b41027aa1..9b4541b1e 100644
--- a/surfsense_web/contracts/types/workspace.types.ts
+++ b/surfsense_web/contracts/types/workspace.types.ts
@@ -1,7 +1,7 @@
import { z } from "zod";
import { paginationQueryParams } from ".";
-export const searchSpace = z.object({
+export const workspace = z.object({
id: z.number(),
name: z.string(),
description: z.string().nullable(),
@@ -16,9 +16,9 @@ export const searchSpace = z.object({
});
/**
- * Get search spaces
+ * Get workspaces
*/
-export const getSearchSpacesRequest = z.object({
+export const getWorkspacesRequest = z.object({
queryParams: paginationQueryParams
.extend({
owned_only: z.boolean().optional(),
@@ -26,31 +26,31 @@ export const getSearchSpacesRequest = z.object({
.nullish(),
});
-export const getSearchSpacesResponse = z.array(searchSpace);
+export const getWorkspacesResponse = z.array(workspace);
/**
- * Create search space
+ * Create workspace
*/
-export const createSearchSpaceRequest = searchSpace.pick({ name: true, description: true }).extend({
+export const createWorkspaceRequest = workspace.pick({ name: true, description: true }).extend({
citations_enabled: z.boolean().prefault(true).optional(),
qna_custom_instructions: z.string().nullable().optional(),
});
-export const createSearchSpaceResponse = searchSpace.omit({ member_count: true, is_owner: true });
+export const createWorkspaceResponse = workspace.omit({ member_count: true, is_owner: true });
/**
- * Get search space
+ * Get workspace
*/
-export const getSearchSpaceRequest = searchSpace.pick({ id: true });
+export const getWorkspaceRequest = workspace.pick({ id: true });
-export const getSearchSpaceResponse = searchSpace.omit({ member_count: true, is_owner: true });
+export const getWorkspaceResponse = workspace.omit({ member_count: true, is_owner: true });
/**
- * Update search space
+ * Update workspace
*/
-export const updateSearchSpaceRequest = z.object({
+export const updateWorkspaceRequest = z.object({
id: z.number(),
- data: searchSpace
+ data: workspace
.pick({
name: true,
description: true,
@@ -61,45 +61,45 @@ export const updateSearchSpaceRequest = z.object({
.partial(),
});
-export const updateSearchSpaceResponse = searchSpace.omit({ member_count: true, is_owner: true });
+export const updateWorkspaceResponse = workspace.omit({ member_count: true, is_owner: true });
-export const updateSearchSpaceApiAccessRequest = z.object({
+export const updateWorkspaceApiAccessRequest = z.object({
id: z.number(),
api_access_enabled: z.boolean(),
});
-export const updateSearchSpaceApiAccessResponse = searchSpace.omit({
+export const updateWorkspaceApiAccessResponse = workspace.omit({
member_count: true,
is_owner: true,
});
/**
- * Delete search space
+ * Delete workspace
*/
-export const deleteSearchSpaceRequest = searchSpace.pick({ id: true });
+export const deleteWorkspaceRequest = workspace.pick({ id: true });
-export const deleteSearchSpaceResponse = z.object({
+export const deleteWorkspaceResponse = z.object({
message: z.literal("Workspace deleted successfully"),
});
/**
- * Leave search space (for non-owners)
+ * Leave workspace (for non-owners)
*/
-export const leaveSearchSpaceResponse = z.object({
+export const leaveWorkspaceResponse = z.object({
message: z.literal("Successfully left the workspace"),
});
// Inferred types
-export type SearchSpace = z.infer;
-export type GetSearchSpacesRequest = z.infer;
-export type GetSearchSpacesResponse = z.infer;
-export type CreateSearchSpaceRequest = z.infer;
-export type CreateSearchSpaceResponse = z.infer;
-export type GetSearchSpaceRequest = z.infer;
-export type GetSearchSpaceResponse = z.infer;
-export type UpdateSearchSpaceRequest = z.infer;
-export type UpdateSearchSpaceResponse = z.infer;
-export type UpdateSearchSpaceApiAccessRequest = z.infer;
-export type UpdateSearchSpaceApiAccessResponse = z.infer;
-export type DeleteSearchSpaceRequest = z.infer;
-export type DeleteSearchSpaceResponse = z.infer;
+export type Workspace = z.infer;
+export type GetWorkspacesRequest = z.infer;
+export type GetWorkspacesResponse = z.infer;
+export type CreateWorkspaceRequest = z.infer;
+export type CreateWorkspaceResponse = z.infer;
+export type GetWorkspaceRequest = z.infer;
+export type GetWorkspaceResponse = z.infer;
+export type UpdateWorkspaceRequest = z.infer;
+export type UpdateWorkspaceResponse = z.infer;
+export type UpdateWorkspaceApiAccessRequest = z.infer;
+export type UpdateWorkspaceApiAccessResponse = z.infer;
+export type DeleteWorkspaceRequest = z.infer;
+export type DeleteWorkspaceResponse = z.infer;
diff --git a/surfsense_web/features/artifacts-library/hooks/use-library-artifacts.ts b/surfsense_web/features/artifacts-library/hooks/use-library-artifacts.ts
index e9ed68633..af53d35f9 100644
--- a/surfsense_web/features/artifacts-library/hooks/use-library-artifacts.ts
+++ b/surfsense_web/features/artifacts-library/hooks/use-library-artifacts.ts
@@ -19,12 +19,12 @@ function videoStatus(status: string): LibraryArtifactStatus {
// Each list is fetched independently; one failing source shouldn't blank the
// whole library, so failures degrade to an empty slice.
-async function fetchLibraryArtifacts(searchSpaceId: number): Promise {
+async function fetchLibraryArtifacts(workspaceId: number): Promise {
const [reports, podcasts, videos, images] = await Promise.all([
- reportsApiService.list(searchSpaceId).catch(() => []),
- podcastsApiService.list(searchSpaceId).catch(() => []),
- videoPresentationsApiService.list(searchSpaceId).catch(() => []),
- imageGenerationsApiService.list(searchSpaceId).catch(() => []),
+ reportsApiService.list(workspaceId).catch(() => []),
+ podcastsApiService.list(workspaceId).catch(() => []),
+ videoPresentationsApiService.list(workspaceId).catch(() => []),
+ imageGenerationsApiService.list(workspaceId).catch(() => []),
]);
const artifacts: LibraryArtifact[] = [];
@@ -86,11 +86,11 @@ async function fetchLibraryArtifacts(searchSpaceId: number): Promise fetchLibraryArtifacts(searchSpaceId),
- enabled: Number.isFinite(searchSpaceId) && searchSpaceId > 0,
+ queryKey: ["artifacts-library", workspaceId],
+ queryFn: () => fetchLibraryArtifacts(workspaceId),
+ enabled: Number.isFinite(workspaceId) && workspaceId > 0,
staleTime: 60 * 1000,
});
diff --git a/surfsense_web/features/artifacts-library/model/artifact.ts b/surfsense_web/features/artifacts-library/model/artifact.ts
index d55751737..9c726f5c0 100644
--- a/surfsense_web/features/artifacts-library/model/artifact.ts
+++ b/surfsense_web/features/artifacts-library/model/artifact.ts
@@ -1,10 +1,10 @@
-/** Deliverable kinds surfaced in the search-space-wide artifacts library. */
+/** Deliverable kinds surfaced in the workspace-wide artifacts library. */
export type LibraryArtifactKind = "report" | "resume" | "podcast" | "video" | "image";
export type LibraryArtifactStatus = "ready" | "running" | "error";
/**
- * A deliverable aggregated from the search space's list endpoints. The heavy
+ * A deliverable aggregated from the workspace's list endpoints. The heavy
* content (report body, audio, video frames, image bytes) is fetched lazily by
* the viewer when a card is opened.
*/
diff --git a/surfsense_web/features/artifacts-library/ui/artifact-card.tsx b/surfsense_web/features/artifacts-library/ui/artifact-card.tsx
index c0ffd1f93..d8abea14a 100644
--- a/surfsense_web/features/artifacts-library/ui/artifact-card.tsx
+++ b/surfsense_web/features/artifacts-library/ui/artifact-card.tsx
@@ -6,11 +6,11 @@ import { KIND_META } from "./kind-meta";
export function ArtifactCard({
artifact,
- searchSpaceId,
+ workspaceId,
onOpen,
}: {
artifact: LibraryArtifact;
- searchSpaceId: number;
+ workspaceId: number;
onOpen: (artifact: LibraryArtifact) => void;
}) {
const meta = KIND_META[artifact.kind];
@@ -50,7 +50,7 @@ export function ArtifactCard({
{artifact.sourceThreadId ? (
diff --git a/surfsense_web/features/artifacts-library/ui/artifacts-library.tsx b/surfsense_web/features/artifacts-library/ui/artifacts-library.tsx
index 3c2d3f368..53010fba2 100644
--- a/surfsense_web/features/artifacts-library/ui/artifacts-library.tsx
+++ b/surfsense_web/features/artifacts-library/ui/artifacts-library.tsx
@@ -33,7 +33,7 @@ function ErrorState({ onRetry }: { onRetry: () => void }) {
Couldn't load artifacts
- Something went wrong fetching this search space's deliverables.
+ Something went wrong fetching this workspace's deliverables.