Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds an open-source “LiteParse + Moss + LlamaIndex” demo app, consisting of a Next.js frontend for uploading/querying PDFs and a FastAPI backend that parses PDFs, chunks them, builds a Moss index, and streams retrieval results via SSE.
Changes:
- Added a Next.js (App Router) frontend with Tailwind styling and demo UX (upload, indexing progress, retrieval display).
- Added a FastAPI backend with upload → parse → chunk → index flow and SSE-based retrieval endpoint, plus a seeding script and Docker image.
- Added static assets (icons/logos) and basic project configuration (.gitignore, PostCSS, TS config, lockfiles).
Reviewed changes
Copilot reviewed 21 out of 28 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/moss-llamaindex/frontend/tsconfig.json | TypeScript configuration for the demo frontend. |
| apps/moss-llamaindex/frontend/public/X.svg | Added X icon asset. |
| apps/moss-llamaindex/frontend/public/liteparse.png | Added LiteParse image asset. |
| apps/moss-llamaindex/frontend/public/Icon.png | Added app icon asset. |
| apps/moss-llamaindex/frontend/public/Favicon.svg | Added favicon asset. |
| apps/moss-llamaindex/frontend/postcss.config.mjs | Tailwind PostCSS configuration. |
| apps/moss-llamaindex/frontend/package.json | Frontend dependencies/scripts (Next/React/Tailwind/UI libs). |
| apps/moss-llamaindex/frontend/package-lock.json | Frontend dependency lockfile. |
| apps/moss-llamaindex/frontend/next.config.mjs | Next.js config (headers/images settings). |
| apps/moss-llamaindex/frontend/next-env.d.ts | Next.js TypeScript env declarations. |
| apps/moss-llamaindex/frontend/lib/utils.ts | Utility for className merging (cn). |
| apps/moss-llamaindex/frontend/components/ui/button.tsx | Reusable Button component/variants. |
| apps/moss-llamaindex/frontend/components/demo/upload-section.tsx | Upload UI with drag/drop and file list. |
| apps/moss-llamaindex/frontend/components/demo/indexing-progress.tsx | Indexing progress UI/animation. |
| apps/moss-llamaindex/frontend/components/demo/chat-section.tsx | Retrieval “chat” UI consuming SSE stream. |
| apps/moss-llamaindex/frontend/components/common/navbar.tsx | Demo site navbar with mobile drawer. |
| apps/moss-llamaindex/frontend/components/common/footer.tsx | Demo site footer with external links/social icons. |
| apps/moss-llamaindex/frontend/app/page.tsx | Main demo page flow (upload → indexing → ready). |
| apps/moss-llamaindex/frontend/app/layout.tsx | App layout, metadata, fonts, navbar/footer, toaster. |
| apps/moss-llamaindex/frontend/app/globals.css | Tailwind import + global styles and tokens. |
| apps/moss-llamaindex/backend/seed_index.py | Script to pre-index a PDF into Moss for reuse. |
| apps/moss-llamaindex/backend/requirements.txt | Backend Python dependencies. |
| apps/moss-llamaindex/backend/package.json | Backend dev dependency for LiteParse CLI. |
| apps/moss-llamaindex/backend/main.py | FastAPI backend implementing upload/index/query endpoints. |
| apps/moss-llamaindex/backend/Dockerfile | Docker image for the backend with Node + LiteParse CLI. |
| apps/moss-llamaindex/backend/.dockerignore | Docker ignore rules for backend build context. |
| apps/moss-llamaindex/.gitignore | Repo ignore rules for the moss-llamaindex app. |
Files not reviewed (1)
- apps/moss-llamaindex/frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const nextConfig = { | ||
| poweredByHeader: false, | ||
| reactStrictMode: true, | ||
| images: { | ||
| remotePatterns: [{ protocol: 'https', hostname: '**' }], |
There was a problem hiding this comment.
images.remotePatterns is configured to allow https://** (any hostname), which means the Next.js image optimizer can be abused to fetch arbitrary remote URLs. Consider restricting this to the specific hostnames you need (or removing remotePatterns entirely if not required).
| const nextConfig = { | |
| poweredByHeader: false, | |
| reactStrictMode: true, | |
| images: { | |
| remotePatterns: [{ protocol: 'https', hostname: '**' }], | |
| const allowedImageHostnames = (process.env.NEXT_IMAGE_REMOTE_HOSTNAMES ?? '') | |
| .split(',') | |
| .map((hostname) => hostname.trim()) | |
| .filter(Boolean); | |
| const nextConfig = { | |
| poweredByHeader: false, | |
| reactStrictMode: true, | |
| images: { | |
| remotePatterns: allowedImageHostnames.map((hostname) => ({ | |
| protocol: 'https', | |
| hostname, | |
| })), |
| @app.middleware("http") | ||
| async def add_hsts_header(request, call_next): | ||
| response = await call_next(request) | ||
| response.headers["Strict-Transport-Security"] = "max-age=30" | ||
| return response | ||
|
|
||
|
|
||
| app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) | ||
|
|
There was a problem hiding this comment.
allow_origins=["*"] effectively disables CORS protection for this API. If this is intended for local demos only, consider making allowed origins configurable via env var and defaulting to a safer value in production deployments.
| @app.middleware("http") | ||
| async def add_hsts_header(request, call_next): | ||
| response = await call_next(request) | ||
| response.headers["Strict-Transport-Security"] = "max-age=30" | ||
| return response |
There was a problem hiding this comment.
Strict-Transport-Security is being set for all requests with max-age=30. HSTS should generally only be sent over HTTPS and usually with a much longer max-age; consider making this conditional (e.g., only when behind TLS / in production) or removing it for local dev to avoid confusing client behavior.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| const apiPromise = fetch(`${API_URL}/api/sample`).then((r) => { | ||
| if (!r.ok) throw new Error('Failed to load sample'); | ||
| return r.json(); | ||
| }); |
There was a problem hiding this comment.
🟡 Unhandled promise rejection in loadSample when API call fails during animation
The apiPromise is created outside the try block at line 92, but isn't awaited until line 104, after a ~4-second animation loop. If the fetch rejects quickly (e.g., network error, backend is down), the promise is rejected with no .catch() handler attached for up to 4 seconds. This triggers the browser's unhandledrejection event, which logs console errors and fires global error handlers (e.g., Sentry). The error IS eventually caught when await apiPromise runs inside the try, but the unhandledrejection event has already fired.
Fix approach
Either move the fetch call inside the try block, or attach a no-op .catch() to suppress the intermediate rejection: const apiPromise = fetch(...).then(...).catch(() => { throw ... }) — or simply store a caught version and re-throw on await.
Prompt for agents
In the loadSample callback in apps/moss-llamaindex/frontend/app/page.tsx, the fetch promise (apiPromise) is created at line 92 outside the try block but not awaited until line 104, after a 4-second animation loop. If the fetch rejects quickly (e.g. backend is down), the browser fires an unhandledrejection event during the animation window because no .catch() is attached.
The simplest fix is to move the fetch call inside the try block, or store the rejection for later re-throw:
Option A: Move inside try:
try {
const apiPromise = fetch(...)...
for (animation loop)...
const data = await apiPromise;
}
Option B: Swallow-and-rethrow pattern:
let apiError;
const apiPromise = fetch(...)...catch(e => { apiError = e; });
try {
for (animation loop)...
if (apiError) throw apiError;
const data = await apiPromise;
}
Option A is simpler and preferred.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
is this ready for review ? |
Pull Request Checklist
Please ensure that your PR meets the following requirements:
Description
Open sourcing code of llama index demo
Type of Change