Merge remote-tracking branch 'upstream/ci_mvp' into feat/ci-ui-changes

This commit is contained in:
Anish Sarkar 2026-07-06 13:25:51 +05:30
commit fd8d1273cd
188 changed files with 2163 additions and 3644 deletions

View file

@ -5,7 +5,7 @@ const AgentActionReadSchema = z.object({
id: z.number(),
thread_id: z.number(),
user_id: z.string().nullable(),
search_space_id: z.number(),
workspace_id: z.number(),
tool_name: z.string(),
args: z.record(z.string(), z.unknown()).nullable(),
result_id: z.string().nullable(),

View file

@ -7,7 +7,7 @@ export type AgentPermissionAction = z.infer<typeof ActionEnum>;
const AgentPermissionRuleSchema = z.object({
id: z.number(),
search_space_id: z.number(),
workspace_id: z.number(),
user_id: z.string().nullable(),
thread_id: z.number().nullable(),
permission: z.string(),

View file

@ -37,7 +37,7 @@ class AutomationsApiService {
listAutomations = async (params: AutomationListParams) => {
const qs = new URLSearchParams({
workspace_id: String(params.search_space_id),
workspace_id: String(params.workspace_id),
limit: String(params.limit),
offset: String(params.offset),
});
@ -50,9 +50,9 @@ class AutomationsApiService {
createAutomation = async (request: AutomationCreateRequest) => {
const data = rejectIfInvalid(automationCreateRequest.safeParse(request));
const { search_space_id, ...body } = data;
const { workspace_id, ...body } = data;
return baseApiService.post(BASE, automation, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};
@ -66,7 +66,7 @@ class AutomationsApiService {
return baseApiService.delete(`${BASE}/${automationId}`);
};
// Whether the search space's models are billable for automations (premium
// Whether the workspace's models are billable for automations (premium
// global or BYOK). Used to gate creation surfaces before submit.
getModelEligibility = async (searchSpaceId: number) => {
const qs = new URLSearchParams({ workspace_id: String(searchSpaceId) });

View file

@ -139,8 +139,8 @@ class ChatCommentsApiService {
}
const params = new URLSearchParams();
if (parsed.data.search_space_id !== undefined) {
params.set("workspace_id", String(parsed.data.search_space_id));
if (parsed.data.workspace_id !== undefined) {
params.set("workspace_id", String(parsed.data.workspace_id));
}
const queryString = params.toString();

View file

@ -73,7 +73,7 @@ class ChatThreadsApiService {
};
/**
* List all public chat snapshots for a search space.
* List all public chat snapshots for a workspace.
*/
listPublicChatSnapshotsForSearchSpace = async (
request: PublicChatSnapshotsBySpaceRequest
@ -86,7 +86,7 @@ class ChatThreadsApiService {
}
return baseApiService.get(
`/api/v1/workspaces/${parsed.data.search_space_id}/snapshots`,
`/api/v1/workspaces/${parsed.data.workspace_id}/snapshots`,
publicChatSnapshotsBySpaceResponse
);
};

View file

@ -41,7 +41,7 @@ import { baseApiService } from "./base-api.service";
class ConnectorsApiService {
/**
* Get all connectors for a search space
* Get all connectors for a workspace
*/
getConnectors = async (request: GetConnectorsRequest) => {
const parsedRequest = getConnectorsRequest.safeParse(request);
@ -59,7 +59,7 @@ class ConnectorsApiService {
Object.entries(parsedRequest.data.queryParams)
.filter(([_, v]) => v !== undefined && v !== null)
.map(([k, v]) => {
return [k === "search_space_id" ? "workspace_id" : k, String(v)];
return [k, String(v)];
})
)
: undefined;
@ -113,7 +113,7 @@ class ConnectorsApiService {
Object.entries(queryParams)
.filter(([_, v]) => v !== undefined && v !== null)
.map(([k, v]) => {
return [k === "search_space_id" ? "workspace_id" : k, String(v)];
return [k, String(v)];
})
);
@ -187,7 +187,7 @@ class ConnectorsApiService {
Object.entries(queryParams)
.filter(([_, v]) => v !== undefined && v !== null)
.map(([k, v]) => {
return [k === "search_space_id" ? "workspace_id" : k, String(v)];
return [k, String(v)];
})
);
@ -308,13 +308,13 @@ class ConnectorsApiService {
// =============================================================================
/**
* Get all MCP connectors for a search space
* Get all MCP connectors for a workspace
*/
getMCPConnectors = async (request: GetMCPConnectorsRequest) => {
const { search_space_id } = request.queryParams;
const { workspace_id } = request.queryParams;
const queryString = new URLSearchParams({
workspace_id: String(search_space_id),
workspace_id: String(workspace_id),
}).toString();
return baseApiService.get<MCPConnectorRead[]>(`/api/v1/connectors/mcp?${queryString}`);
@ -334,7 +334,7 @@ class ConnectorsApiService {
const { data, queryParams } = request;
const queryString = new URLSearchParams({
workspace_id: String(queryParams.search_space_id),
workspace_id: String(queryParams.workspace_id),
}).toString();
return baseApiService.post<MCPConnectorRead>(

View file

@ -61,7 +61,7 @@ class DocumentsApiService {
const transformedQueryParams = parsedRequest.data.queryParams
? Object.fromEntries(
Object.entries(parsedRequest.data.queryParams).map(([k, v]) => {
const key = k === "search_space_id" ? "workspace_id" : k;
const key = k;
// Handle array values (document_type)
if (Array.isArray(v)) {
return [key, v.join(",")];
@ -107,9 +107,9 @@ class DocumentsApiService {
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, ...body } = parsedRequest.data;
const { workspace_id, ...body } = parsedRequest.data;
return baseApiService.post(`/api/v1/documents`, createDocumentResponse, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};
@ -128,7 +128,7 @@ class DocumentsApiService {
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { files, search_space_id, use_vision_llm, processing_mode } = parsedRequest.data;
const { files, workspace_id, use_vision_llm, processing_mode } = parsedRequest.data;
const UPLOAD_BATCH_SIZE = 5;
const batches: File[][] = [];
@ -145,7 +145,7 @@ class DocumentsApiService {
for (const batch of batches) {
const formData = new FormData();
for (const file of batch) formData.append("files", file);
formData.append("workspace_id", String(search_space_id));
formData.append("workspace_id", String(workspace_id));
formData.append("use_vision_llm", String(use_vision_llm));
formData.append("processing_mode", processing_mode);
@ -191,9 +191,9 @@ class DocumentsApiService {
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, document_ids } = parsedRequest.data.queryParams;
const { workspace_id, document_ids } = parsedRequest.data.queryParams;
const params = new URLSearchParams({
workspace_id: String(search_space_id),
workspace_id: String(workspace_id),
document_ids: document_ids.join(","),
});
@ -220,7 +220,7 @@ class DocumentsApiService {
const transformedQueryParams = parsedRequest.data.queryParams
? Object.fromEntries(
Object.entries(parsedRequest.data.queryParams).map(([k, v]) => {
const key = k === "search_space_id" ? "workspace_id" : k;
const key = k;
// Handle array values (document_type)
if (Array.isArray(v)) {
return [key, v.join(",")];
@ -258,7 +258,7 @@ class DocumentsApiService {
Object.entries(parsedRequest.data.queryParams)
.filter(([, v]) => v !== undefined)
.map(([k, v]) => [
k === "search_space_id" || k === "workspace_id" ? "workspace_id" : k,
k,
String(v),
])
);
@ -272,9 +272,9 @@ class DocumentsApiService {
);
};
getDocumentByVirtualPath = async (request: { search_space_id: number; virtual_path: string }) => {
getDocumentByVirtualPath = async (request: { workspace_id: number; virtual_path: string }) => {
const params = new URLSearchParams({
workspace_id: String(request.search_space_id),
workspace_id: String(request.workspace_id),
virtual_path: request.virtual_path,
});
return baseApiService.get(
@ -302,7 +302,7 @@ class DocumentsApiService {
const transformedQueryParams = parsedRequest.data.queryParams
? Object.fromEntries(
Object.entries(parsedRequest.data.queryParams).map(([k, v]) => [
k === "search_space_id" ? "workspace_id" : k,
k,
String(v),
])
)
@ -384,10 +384,10 @@ class DocumentsApiService {
}
const { id, data } = parsedRequest.data;
const { search_space_id, ...body } = data;
const { workspace_id, ...body } = data;
return baseApiService.put(`/api/v1/documents/${id}`, updateDocumentResponse, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};
@ -413,12 +413,12 @@ class DocumentsApiService {
folderMtimeCheck = async (body: {
folder_name: string;
search_space_id: number;
workspace_id: number;
files: { relative_path: string; mtime: number }[];
}): Promise<{ files_to_upload: string[] }> => {
const { search_space_id, ...rest } = body;
const { workspace_id, ...rest } = body;
return baseApiService.post(`/api/v1/documents/folder-mtime-check`, undefined, {
body: { ...rest, workspace_id: search_space_id },
body: { ...rest, workspace_id },
}) as unknown as { files_to_upload: string[] };
};
@ -426,7 +426,7 @@ class DocumentsApiService {
files: File[],
metadata: {
folder_name: string;
search_space_id: number;
workspace_id: number;
relative_paths: string[];
root_folder_id?: number | null;
use_vision_llm?: boolean;
@ -439,7 +439,7 @@ class DocumentsApiService {
formData.append("files", file);
}
formData.append("folder_name", metadata.folder_name);
formData.append("workspace_id", String(metadata.search_space_id));
formData.append("workspace_id", String(metadata.workspace_id));
formData.append("relative_paths", JSON.stringify(metadata.relative_paths));
if (metadata.root_folder_id != null) {
formData.append("root_folder_id", String(metadata.root_folder_id));
@ -469,25 +469,25 @@ class DocumentsApiService {
folderNotifyUnlinked = async (body: {
folder_name: string;
search_space_id: number;
workspace_id: number;
root_folder_id: number | null;
relative_paths: string[];
}): Promise<{ deleted_count: number }> => {
const { search_space_id, ...rest } = body;
const { workspace_id, ...rest } = body;
return baseApiService.post(`/api/v1/documents/folder-unlink`, undefined, {
body: { ...rest, workspace_id: search_space_id },
body: { ...rest, workspace_id },
}) as unknown as { deleted_count: number };
};
folderSyncFinalize = async (body: {
folder_name: string;
search_space_id: number;
workspace_id: number;
root_folder_id: number | null;
all_relative_paths: string[];
}): Promise<{ deleted_count: number }> => {
const { search_space_id, ...rest } = body;
const { workspace_id, ...rest } = body;
return baseApiService.post(`/api/v1/documents/folder-sync-finalize`, undefined, {
body: { ...rest, workspace_id: search_space_id },
body: { ...rest, workspace_id },
}) as unknown as { deleted_count: number };
};

View file

@ -27,9 +27,9 @@ class FoldersApiService {
`Invalid request: ${parsed.error.issues.map((i) => i.message).join(", ")}`
);
}
const { search_space_id, ...body } = parsed.data;
const { workspace_id, ...body } = parsed.data;
return baseApiService.post("/api/v1/folders", folder, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};

View file

@ -36,7 +36,7 @@ class InvitesApiService {
}
return baseApiService.post(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/invites`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/invites`,
createInviteResponse,
{
body: parsedRequest.data.data,
@ -45,7 +45,7 @@ class InvitesApiService {
};
/**
* Get all invites for a search space
* Get all invites for a workspace
*/
getInvites = async (request: GetInvitesRequest) => {
const parsedRequest = getInvitesRequest.safeParse(request);
@ -58,7 +58,7 @@ class InvitesApiService {
}
return baseApiService.get(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/invites`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/invites`,
getInvitesResponse
);
};
@ -77,7 +77,7 @@ class InvitesApiService {
}
return baseApiService.put(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/invites/${parsedRequest.data.invite_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/invites/${parsedRequest.data.invite_id}`,
updateInviteResponse,
{
body: parsedRequest.data.data,
@ -99,7 +99,7 @@ class InvitesApiService {
}
return baseApiService.delete(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/invites/${parsedRequest.data.invite_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/invites/${parsedRequest.data.invite_id}`,
deleteInviteResponse
);
};

View file

@ -36,7 +36,7 @@ class LogsApiService {
const transformedQueryParams = parsedRequest.data.queryParams
? Object.fromEntries(
Object.entries(parsedRequest.data.queryParams).map(([k, v]) => {
const key = k === "search_space_id" ? "workspace_id" : k;
const key = k;
// Handle array values (document_type)
if (Array.isArray(v)) {
return [key, v.join(",")];
@ -75,9 +75,9 @@ class LogsApiService {
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, ...body } = parsedRequest.data;
const { workspace_id, ...body } = parsedRequest.data;
return baseApiService.post(`/api/v1/logs`, createLogResponse, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};
@ -91,9 +91,9 @@ class LogsApiService {
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, ...body } = parsedRequest.data;
const { workspace_id, ...body } = parsedRequest.data;
return baseApiService.put(`/api/v1/logs/${logId}`, updateLogResponse, {
body: search_space_id === undefined ? body : { ...body, workspace_id: search_space_id },
body: workspace_id === undefined ? body : { ...body, workspace_id },
});
};
@ -111,7 +111,7 @@ class LogsApiService {
};
/**
* Get summary for logs by search space
* Get summary for logs by workspace
*/
getLogSummary = async (request: GetLogSummaryRequest) => {
const parsedRequest = getLogSummaryRequest.safeParse(request);
@ -120,8 +120,8 @@ class LogsApiService {
const errorMessage = parsedRequest.error.issues.map((issue) => issue.message).join(", ");
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, hours } = parsedRequest.data;
const url = `/api/v1/logs/workspaces/${search_space_id}/summary${hours ? `?hours=${hours}` : ""}`;
const { workspace_id, hours } = parsedRequest.data;
const url = `/api/v1/logs/workspaces/${workspace_id}/summary${hours ? `?hours=${hours}` : ""}`;
return baseApiService.get(url, getLogSummaryResponse);
};
}

View file

@ -20,7 +20,7 @@ import { baseApiService } from "./base-api.service";
class MembersApiService {
/**
* Get members of a search space
* Get members of a workspace
*/
getMembers = async (request: GetMembersRequest) => {
const parsedRequest = getMembersRequest.safeParse(request);
@ -33,7 +33,7 @@ class MembersApiService {
}
return baseApiService.get(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/members`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/members`,
getMembersResponse
);
};
@ -52,7 +52,7 @@ class MembersApiService {
}
return baseApiService.put(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/members/${parsedRequest.data.membership_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/members/${parsedRequest.data.membership_id}`,
updateMembershipResponse,
{
body: parsedRequest.data.data,
@ -61,7 +61,7 @@ class MembersApiService {
};
/**
* Delete a member from search space
* Delete a member from workspace
*/
deleteMember = async (request: DeleteMembershipRequest) => {
const parsedRequest = deleteMembershipRequest.safeParse(request);
@ -74,13 +74,13 @@ class MembersApiService {
}
return baseApiService.delete(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/members/${parsedRequest.data.membership_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/members/${parsedRequest.data.membership_id}`,
deleteMembershipResponse
);
};
/**
* Leave a search space (remove self)
* Leave a workspace (remove self)
*/
leaveSearchSpace = async (request: LeaveSearchSpaceRequest) => {
const parsedRequest = leaveSearchSpaceRequest.safeParse(request);
@ -93,13 +93,13 @@ class MembersApiService {
}
return baseApiService.delete(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/members/me`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/members/me`,
leaveSearchSpaceResponse
);
};
/**
* Get current user's access information for a search space
* Get current user's access information for a workspace
*/
getMyAccess = async (request: GetMyAccessRequest) => {
const parsedRequest = getMyAccessRequest.safeParse(request);
@ -112,7 +112,7 @@ class MembersApiService {
}
return baseApiService.get(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/my-access`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/my-access`,
getMyAccessResponse
);
};

View file

@ -56,15 +56,15 @@ class ModelConnectionsApiService {
if (!parsed.success) {
throw new ValidationError(parsed.error.issues.map((issue) => issue.message).join(", "));
}
const { search_space_id, ...body } = parsed.data;
const { workspace_id, ...body } = parsed.data;
if (
body.scope === "SEARCH_SPACE" &&
(!Number.isFinite(search_space_id) || (search_space_id ?? 0) <= 0)
(!Number.isFinite(workspace_id) || (workspace_id ?? 0) <= 0)
) {
throw new ValidationError("workspace_id is required");
}
return baseApiService.post(`/api/v1/model-connections`, connectionRead, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};
@ -98,10 +98,10 @@ class ModelConnectionsApiService {
if (!parsed.success) {
throw new ValidationError(parsed.error.issues.map((issue) => issue.message).join(", "));
}
const { search_space_id, ...body } = parsed.data;
const { workspace_id, ...body } = parsed.data;
if (
body.scope === "SEARCH_SPACE" &&
(!Number.isFinite(search_space_id) || (search_space_id ?? 0) <= 0)
(!Number.isFinite(workspace_id) || (workspace_id ?? 0) <= 0)
) {
throw new ValidationError("workspace_id is required");
}
@ -109,7 +109,7 @@ class ModelConnectionsApiService {
`/api/v1/model-connections/discover-preview`,
modelPreviewListResponse,
{
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
}
);
};
@ -121,15 +121,15 @@ class ModelConnectionsApiService {
if (!parsed.success) {
throw new ValidationError(parsed.error.issues.map((issue) => issue.message).join(", "));
}
const { search_space_id, ...body } = parsed.data;
const { workspace_id, ...body } = parsed.data;
if (
body.scope === "SEARCH_SPACE" &&
(!Number.isFinite(search_space_id) || (search_space_id ?? 0) <= 0)
(!Number.isFinite(workspace_id) || (workspace_id ?? 0) <= 0)
) {
throw new ValidationError("workspace_id is required");
}
return baseApiService.post(`/api/v1/model-connections/test-preview`, verifyConnectionResponse, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};

View file

@ -41,8 +41,8 @@ class NotificationsApiService {
// Build query string from params
const params = new URLSearchParams();
if (queryParams.search_space_id !== undefined) {
params.append("workspace_id", String(queryParams.search_space_id));
if (queryParams.workspace_id !== undefined) {
params.append("workspace_id", String(queryParams.workspace_id));
}
if (queryParams.type) {
params.append("type", queryParams.type);

View file

@ -30,9 +30,9 @@ class PromptsApiService {
throw new ValidationError(`Invalid request: ${errorMessage}`);
}
const { search_space_id, ...body } = parsed.data;
const { workspace_id, ...body } = parsed.data;
return baseApiService.post("/api/v1/prompts", promptRead, {
body: { ...body, workspace_id: search_space_id },
body: { ...body, workspace_id },
});
};

View file

@ -30,7 +30,7 @@ class RolesApiService {
}
return baseApiService.post(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/roles`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/roles`,
createRoleResponse,
{
body: parsedRequest.data.data,
@ -49,7 +49,7 @@ class RolesApiService {
}
return baseApiService.get(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/roles`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/roles`,
getRolesResponse
);
};
@ -65,7 +65,7 @@ class RolesApiService {
}
return baseApiService.get(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/roles/${parsedRequest.data.role_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/roles/${parsedRequest.data.role_id}`,
getRoleByIdResponse
);
};
@ -81,7 +81,7 @@ class RolesApiService {
}
return baseApiService.put(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/roles/${parsedRequest.data.role_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/roles/${parsedRequest.data.role_id}`,
updateRoleResponse,
{
body: parsedRequest.data.data,
@ -100,7 +100,7 @@ class RolesApiService {
}
return baseApiService.delete(
`/api/v1/workspaces/${parsedRequest.data.search_space_id}/roles/${parsedRequest.data.role_id}`,
`/api/v1/workspaces/${parsedRequest.data.workspace_id}/roles/${parsedRequest.data.role_id}`,
deleteRoleResponse
);
};

View file

@ -23,11 +23,11 @@ class StripeApiService {
createCreditCheckoutSession = async (
request: CreateCreditCheckoutSessionRequest
): Promise<CreateCreditCheckoutSessionResponse> => {
const { search_space_id, ...body } = request;
const { workspace_id, ...body } = request;
return baseApiService.post(
"/api/v1/stripe/create-credit-checkout-session",
createCreditCheckoutSessionResponse,
{ body: { ...body, workspace_id: search_space_id } }
{ body: { ...body, workspace_id } }
);
};
@ -75,11 +75,11 @@ class StripeApiService {
createAutoReloadSetupSession = async (
request: CreateAutoReloadSetupSessionRequest
): Promise<CreateAutoReloadSetupSessionResponse> => {
const { search_space_id } = request;
const { workspace_id } = request;
return baseApiService.post(
"/api/v1/stripe/auto-reload/setup",
createAutoReloadSetupSessionResponse,
{ body: { workspace_id: search_space_id } }
{ body: { workspace_id } }
);
};
}

View file

@ -19,7 +19,7 @@ import {
updateSearchSpaceApiAccessResponse,
updateSearchSpaceRequest,
updateSearchSpaceResponse,
} from "@/contracts/types/search-space.types";
} from "@/contracts/types/workspace.types";
import { ValidationError } from "../error";
import { baseApiService } from "./base-api.service";
@ -139,6 +139,17 @@ class SearchSpacesApiService {
return baseApiService.delete(`/api/v1/workspaces/${request.id}`, deleteSearchSpaceResponse);
};
/**
* Trigger AI file sorting for all documents in a search space
*/
triggerAiSort = async (searchSpaceId: number) => {
return baseApiService.post(
`/api/v1/workspaces/${searchSpaceId}/ai-sort`,
z.object({ message: z.string() }),
{}
);
};
/**
* Leave a search space (remove own membership)
* This is used by non-owners to leave a shared search space