Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion src/app/api/source-uploads/blob/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe("POST /api/source-uploads/blob", () => {
mocks.getCurrentUser.mockResolvedValue({ id: "user_1" });
});

it("generates a public client-upload token capped at the 100 MB document limit", async () => {
it("generates a public client-upload token capped at the document upload limit", async () => {
mocks.handleUpload.mockImplementation(async (options) => {
const tokenOptions = await options.onBeforeGenerateToken(
"source-uploads/upload_1/document.pdf",
Expand Down
4 changes: 3 additions & 1 deletion src/components/chunks-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
import { useChunksPanelWorkflow } from "@/components/chunks-panel-workflow";
import { ParsedChunkCard } from "@/components/parsed-chunk-card";
import { chunksPanelState } from "@/components/chunks-panel-state";
import { MAX_UPLOAD_MB } from "@/domains/sources/validation";
import { useSourceOriginalPreviewWarmup } from "@/components/source-original-preview-warmup";
import { sourceOriginalPreviewModel } from "@/components/source-original-preview-model";
import type { ParsedChunkView } from "@/domains/chunks/types";
Expand Down Expand Up @@ -1006,7 +1007,8 @@ function EmptySourceUploadState({
parsed chunks and chat.
</span>
<span className="rounded-md border border-border bg-background px-2.5 py-1 text-[11px] font-medium text-muted-foreground shadow-sm">
PDF, DOCX, TXT, MD, spreadsheets, slides, and images up to 100 MB
PDF, DOCX, TXT, MD, spreadsheets, slides, and images up to{" "}
{MAX_UPLOAD_MB} MB
</span>
</button>
)}
Expand Down
6 changes: 4 additions & 2 deletions src/components/source-upload-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "@/components/ui/dialog";
import { useSourceUploadDialogWorkflow } from "@/components/source-upload-dialog-workflow";
import type { SourceView } from "@/domains/sources/types";
import { MAX_UPLOAD_MB } from "@/domains/sources/validation";

export type SourceUploadDialogProps = {
readonly onSourceUploaded?: (source: SourceView) => void;
Expand Down Expand Up @@ -84,7 +85,8 @@ export function SourceUploadDialog({
<DialogTitle>Add source</DialogTitle>
<DialogDescription>
Add a document to your notebook. Notebook accepts PDF, DOC, DOCX,
TXT, MD, XLS, XLSX, PPTX, images, and more files up to 100 MB.
TXT, MD, XLS, XLSX, PPTX, images, and more files up to{" "}
{MAX_UPLOAD_MB} MB.
</DialogDescription>
</DialogHeader>
<form
Expand Down Expand Up @@ -117,7 +119,7 @@ export function SourceUploadDialog({
Click to select or drag and drop a document
</p>
<p className="mt-2 rounded-md border border-border bg-background px-2.5 py-1 text-[11px] font-medium text-muted-foreground shadow-sm">
Max size: 100 MB
Max size: {MAX_UPLOAD_MB} MB
</p>
{selectedFileName && (
<p className="mt-3 max-w-full truncate text-xs font-medium text-foreground">
Expand Down
15 changes: 7 additions & 8 deletions src/components/sources-panel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import { SourcesPanel } from "./sources-panel";

const C = SourcesPanel as React.FC<Record<string, unknown>>;
const originalResizeObserver = globalThis.ResizeObserver;
const fileTooLargeMessage =
"File is too large. Upload a document up to 300 MB. " +
"For larger files, contact team@knowhereto.ai or open an issue at https://github.com/Ontos-AI/knowhere/issues.";

describe("SourcesPanel", () => {
beforeEach(() => {
Expand Down Expand Up @@ -131,10 +134,10 @@ describe("SourcesPanel", () => {

expect(
screen.getByText(
/Notebook accepts PDF, DOC, DOCX, TXT, MD, XLS, XLSX, PPTX, images, and more files up to 100 MB/,
/Notebook accepts PDF, DOC, DOCX, TXT, MD, XLS, XLSX, PPTX, images, and more files up to 300 MB/,
),
).toBeTruthy();
expect(screen.getByText("Max size: 100 MB")).toBeTruthy();
expect(screen.getByText("Max size: 300 MB")).toBeTruthy();
expect(opened.container.textContent).not.toMatch(/Knowhere|parsing|indexing/i);
});

Expand Down Expand Up @@ -383,7 +386,7 @@ describe("SourcesPanel", () => {
}

return Response.json(
{ message: "File is too large. Upload a document up to 100 MB." },
{ message: fileTooLargeMessage },
{ status: 400 },
);
});
Expand All @@ -407,11 +410,7 @@ describe("SourcesPanel", () => {
}
fireEvent.submit(form);

expect(
await screen.findByText(
"File is too large. Upload a document up to 100 MB.",
),
).toBeTruthy();
expect(await screen.findByText(fileTooLargeMessage)).toBeTruthy();
expect(screen.getByRole("button", { name: "Confirm" })).toBeTruthy();
});
});
Expand Down
16 changes: 16 additions & 0 deletions src/domains/sources/blob-upload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getSourceUploadBlobPathname,
validateSourceBlobUploadInput,
} from "./blob-upload";
import { FILE_TOO_LARGE_MESSAGE, MAX_UPLOAD_BYTES } from "./validation";

describe("source Blob upload metadata", () => {
afterEach(() => {
Expand Down Expand Up @@ -62,4 +63,19 @@ describe("source Blob upload metadata", () => {
message: "Invalid upload URL. Choose the document again.",
});
});

it("rejects staged upload metadata larger than the upload limit", () => {
const result = validateSourceBlobUploadInput({
pathname: "source-uploads/upload_1/document.pdf",
url: "https://store.public.blob.vercel-storage.com/source-uploads/upload_1/document.pdf",
fileName: "oversized.pdf",
mimeType: "application/pdf",
sizeBytes: MAX_UPLOAD_BYTES + 1,
});

expect(result).toEqual({
ok: false,
message: FILE_TOO_LARGE_MESSAGE,
});
});
});
3 changes: 2 additions & 1 deletion src/domains/sources/blob-upload.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
FILE_TOO_LARGE_MESSAGE,
MAX_UPLOAD_BYTES,
validateUploadFile,
type UploadValidationResult,
Expand Down Expand Up @@ -123,7 +124,7 @@ export function validateSourceBlobUploadMetadata(
if (input.sizeBytes > MAX_UPLOAD_BYTES) {
return {
ok: false,
message: "File is too large. Upload a document up to 100 MB.",
message: FILE_TOO_LARGE_MESSAGE,
};
}

Expand Down
9 changes: 6 additions & 3 deletions src/domains/sources/validation.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { describe, expect, it } from "vitest";

import {
FILE_TOO_LARGE_MESSAGE,
MAX_UPLOAD_BYTES,
MAX_UPLOAD_MB,
validateUploadFile,
} from "./validation";

describe("validateUploadFile", () => {
it("accepts supported document extensions within 100 MB", () => {
it("accepts supported document extensions within the upload limit", () => {
const result = validateUploadFile({
name: "lecture-notes.PDF",
type: "application/pdf",
Expand Down Expand Up @@ -70,7 +72,7 @@ describe("validateUploadFile", () => {
});
});

it("rejects files larger than the 100 MB limit", () => {
it("rejects files larger than the upload limit", () => {
const result = validateUploadFile({
name: "large.pdf",
type: "application/pdf",
Expand All @@ -79,7 +81,8 @@ describe("validateUploadFile", () => {

expect(result).toEqual({
ok: false,
message: "File is too large. Upload a document up to 100 MB.",
message: FILE_TOO_LARGE_MESSAGE,
});
expect(MAX_UPLOAD_MB).toBe(300);
});
});
10 changes: 8 additions & 2 deletions src/domains/sources/validation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export const MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
export const MAX_UPLOAD_MB = 300;
export const MAX_UPLOAD_BYTES = MAX_UPLOAD_MB * 1024 * 1024;
export const SUPPORT_EMAIL = "team@knowhereto.ai";
export const KNOWHERE_ISSUES_URL = "https://github.com/Ontos-AI/knowhere/issues";
export const FILE_TOO_LARGE_MESSAGE =
`File is too large. Upload a document up to ${MAX_UPLOAD_MB} MB. ` +
`For larger files, contact ${SUPPORT_EMAIL} or open an issue at ${KNOWHERE_ISSUES_URL}.`;

const SUPPORTED_EXTENSIONS = new Set([
"doc",
Expand Down Expand Up @@ -36,7 +42,7 @@ export function validateUploadFile(file: UploadFileInfo): UploadValidationResult
if (file.size > MAX_UPLOAD_BYTES) {
return {
ok: false,
message: "File is too large. Upload a document up to 100 MB.",
message: FILE_TOO_LARGE_MESSAGE,
};
}

Expand Down
Loading